跨域

    • 阿里云  >  教程中心   >  html教程  >  web开发中跨域解决方案  
    • web开发中跨域解决方案
    • 发布时间:2018-03-12 来源:网络 上传者:用户

      关键字: 解决方案 开发 web

      发表文章
    • 摘要:什么是跨域?概念如下:只要协议、域名、端口有任何一个不同,都被当作是不同的域下面是具体的跨域情况详解URL说明是否允许通信http://www.a.com/a.js、http://www.a.com/b.js同一域名下允许http://www.a.com/lab/a.js、http://www.a.com/script/b.js同一域名下不同文件夹允许http://www.a.com:8000/a.js、http://www.a.com/b.js同一域名,不同端口不允许htt
    • 什么是跨域? 
      概念如下:只要协议、域名、端口有任何一个不同,都被当作是不同的域 
      下面是具体的跨域情况详解 

      URL 
      说明 
      是否允许通信 


      http://www.a.com/a.js、http://www.a.com/b.js 
      同一域名下 
      允许 

      http://www.a.com/lab/a.js、http://www.a.com/script/b.js 
      同一域名下不同文件夹 
      允许 

      http://www.a.com:8000/a.js、http://www.a.com/b.js 
      同一域名,不同端口 
      不允许 

      http://www.a.com/a.js、https://www.a.com/b.js 
      同一域名,不同协议 
      不允许 

      http://www.a.com/a.js、http://70.32.92.74/b.js 
      域名和域名对应ip 
      不允许 

      http://www.a.com/a.js、http://script.a.com/b.js 
      主域相同,子域不同 
      不允许(cookie这种情况下也不允许访问) 

      http://www.a.com/a.js、http://a.com/b.js 
      同一域名,不同二级域名(同上) 
      不允许(cookie这种情况下也不允许访问) 

      http://www.cnblogs.com/a.js、http://www.a.com/b.js 
      不同域名 
      不允许 

      一、document.domain跨域 
      原理:相同主域名不同子域名下的页面,可以设置document.domain 
      让它们同域 
      限制:同域document 
      提供的是页面间的互操作,需要载入iframe 
      页面 


      下面几个域名下的页面都是可以通过document.domain
      跨域互操作的:http://a.com/foo
      ,http://b.a.com/bar
      ,http://c.a.com/bar
      。 但只能以页面嵌套的方式来进行页面互操作,比如常见的iframe
      方式就可以完成页面嵌套


      // URL http://a.com/foo 
      var ifr = document.createElement('iframe'); 
      ifr.src = 'http://b.a.com/bar'; 
      ifr.onload = function(){ 
      var ifrdoc = ifr.contentDocument || ifr.contentWindow.document; 
      ifrdoc.getElementsById("foo").innerHTML); 
      }; 
      ifr.style.display = 'none'; 
      document.body.appendChild(ifr); 
      上述代码所在的URL 
      是http://a.com/foo 
      ,它对http://b.a.com/bar 
      的DOM 
      访问要求后者将document.domain 
      往上设置一级 
      // URL http://b.a.com/bar 
      document.domain = 'a.com' 
      document.domain 
      只能从子域设置到主域,往下设置以及往其他域名设置都是不允许的, 在Chrome 
      中给出的错误是这样的 
      Uncaught DOMException: Failed to set the 'domain' property on 'Document': 'baidu.com' is not a suffix of 'b.a.com' 
      二、有src的标签 
      原理:所有具有src 
      属性的HTML 
      标签都是可以跨域的,包括<img> 
      ,<script> 
      限制:需要创建一个DOM 
      对象,只能用于GET 
      方法 

      在document.body 
      中append 
      一个具有src 
      属性的HTML 
      标签,src 
      属性值指向的URL 
      会以GET 
      方法被访问,该访问是可以跨域的 
      其实样式表的<link> 
      标签也是可以跨域的,只要是有src 
      或href 
      的HTML 
      标签都有跨域的能力 

      不同的HTML 
      标签发送HTTP 
      请求的时机不同,例如<img> 
      在更改src 
      属性时就会发送请求,而script 
      ,iframe 
      ,link[rel=stylesheet] 
      只有在添加到DOM 
      树之后才会发送HTTP 
      请求: 
      var img = new Image(); 
      img.src = 'http://some/picture';// 发送HTTP请求 
      var ifr = $('<iframe>', {src: 'http://b.a.com/bar'}); 
      $('body').append(ifr);// 发送HTTP请求 
      三、JSONP 
      原理:<script> 
      是可以跨域的,而且在跨域脚本中可以直接回调当前脚本的函数 
      限制:需要创建一个DOM 
      对象并且添加到DOM 
      树,只能用于GET 
      方法 


      JSONP
      利用的是<script>
      可以跨域的特性,跨域URL
      返回的脚本不仅包含数据,还包含一个回调


      // URL: http://b.a.com/foo 
      var data = { 
      foo: 'bar', 
      bar: 'foo' 
      }; 
      callback(data); 
      然后在我们在主站http://a.com 
      中,可以这样来跨域获取http://b.a.com 
      的数据: 
      // URL: http://a.com/foo 
      var callback = function(data){ 
      // 处理跨域请求得到的数据 
      }; 
      var script = $('<script>', {src: 'http://b.a.com/bar'}); 
      $('body').append(script); 
      其实jQuery 
      已经封装了JSONP 
      的使用,我们可以这样来 
      $.getJSON( "http://b.a.com/bar?callback=callback", function(data){ 
      // 处理跨域请求得到的数据 
      }); 


      $.getJSON
      与$.get
      的区别是前者会把responseText
      转换为JSON
      ,而且当URL
      具有callback
      参数时,jQuery
      将会把它解释为一个JSONP
      请求,创建一个<script>
      标签来完成该请求


      四、navigation 对象 
      原理:iframe 
      之间是共享navigator 
      对象的,用它来传递信息 
      要求:IE6/7 


      有些人注意到了IE6/7
      的一个漏洞:iframe
      之间的window.navigator
      对象是共享的。 我们可以把它作为一个Messenger
      ,通过它来传递信息。比如一个简单的委托:


      // a.com 
      navigation.onData(){ 
      // 数据到达的处理函数 

      typeof navigation.getData === 'function' 
      || navigation.getData() 
      // b.com 
      navigation.getData = function(){ 
      $.get('/path/under/b.com') 
      .success(function(data){ 
      typeof navigation.onData === 'function' 
      || navigation.onData(data) 
      }); 


      与document.navigator
      类似,window.name
      也是当前窗口所有页面所共享的。也可以用它来传递信息。 同样蛋疼的办法还有传递Hash
      (有些人叫锚点),这是因为每次浏览器打开一个URL
      时,URL
      后面的#xxx
      部分会保留下来,那么新的页面可以从这里获得上一个页面的数据


      五、跨域资源共享(CORS) 
      原理:服务器设置Access-Control-Allow-OriginHTTP 
      响应头之后,浏览器将会允许跨域请求 
      限制:浏览器需要支持HTML5 
      ,可以支持POST 
      ,PUT 
      等方法 


      前面提到的跨域手段都是某种意义上的Hack
      ,HTML5
      标准中提出的跨域资源共享(Cross Origin Resource Share
      ,CORS
      )才是正道。 它支持其他的HTTP
      方法如PUT
      ,POST
      等,可以从本质上解决跨域问题。


      例如,从http://a.com 
      要访问http://b.com 
      的数据,通常情况下Chrome 
      会因跨域请求而报错 
      XMLHttpRequest cannot load http://b.com. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://a.com' is therefore not allowed access 
      错误原因是被请求资源没有设置Access-Control-Allow-Origin 
      ,所以我们在b.com 
      的服务器中设置这个响应头字段即可 
      Access-Control-Allow-Origin: *# 允许所有域名访问,或者 
      Access-Control-Allow-Origin: http://a.com # 只允许所有域名访问 
      六、window.postMessage 
      原理:HTML5 
      允许窗口之间发送消息 
      限制:浏览器需要支持HTML5 
      ,获取窗口句柄后才能相互通信 


      这是一个安全的跨域通信方法,postMessage(message,targetOrigin)
      也是HTML5
      引入的特性。 可以给任何一个window
      发送消息,不论是否同源。第二个参数可以是*但如果你设置了一个URL
      但不相符,那么该事件不会被分发。看一个普通的使用方式吧


      // URL: http://a.com/foo 
      var win = window.open('http://b.com/bar'); 
      win.postMessage('Hello, bar!', 'http://b.com'); 
      // URL: http://b.com/bar 
      window.addEventListener('message',function(event){ 
      console.log(event.data); 
      }); 
posted @ 2018-03-24 17:31  2350305682  阅读(227)  评论(0编辑  收藏  举报