zoukankan      html  css  js  c++  java
  • js跨域问题解决方案

     


     跨域:当协议、域名、端口号任何一个不相同时,叫称为跨域。
     
    HTML5  CORS(cross-origin-resource-sharing)跨域资源共享: 原理:当需要访问跨域的资源时,可以通过定义http头信息,使得服务器响应跨域请求。
    如:
    // 使用通配符 * ,表示当前服务端响应任何域名发起请求,不推荐  可以具体指定某个地址
    <?php header('Access-Control-Allow-Origin:*'); ?>
    就这样在服务端简单加一句响应头responese headers声明,一个跨域请求就不会被浏览器的同源安全策略所阻止了!

    在浏览器端通过XHR对象(IE的XDomainRequest对象),实现ajax跨域:


    function corsReq(){
    if(window.
    XMLHttpRequest
    var xhr = new XMLHttpRequest();
    else if(window.XDomainRequest){
    var xhr = new XDomainRequest();
    }
        xhr.open('POST',url,true);  //url使用绝对路径
        xhr.send(data);
        xhr.close();
        .....
    }
    
    
    浏览器检测头信息,在响应头信息中,header中包含了 Access-Control-Allow-Origin这个字段,如果字段值和我们域名相同,浏览器才会使用里面的数据做下一步处理。
    (只有当目标页面的response中,包含了 Access-Control-Allow-Origin 这个header,并且它的值里有我们自己的域名时,浏览器才允许我们拿到它页面的数据进行下一步处理。)
    缺点:IE10以上才支持,IE 8 ie 9通过XDomainRequest支持 

    1、JSON-P跨域

    什么事jsonp?

    利用在页面中创建<script>节点的方法向不同域提交HTTP请求的方法称为JSONP

    动态脚本注入的方法,通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。所以jsonp是需要服务器端的页面进行相应的配合的

    var eleScript= document.createElement("script");
    
    eleScript.type = "text/javascript";
    
    eleScript.src = "http://example2.com/getinfo.php";
    
    document.getElementsByTagName("HEAD")[0].appendChild(eleScript);
     jsonp的方式原理上和<script src="http://跨域/...xx.js"></script>是一致的(qq空间就是大量采用这种方式来实现跨域数据交换的) .JSONP是一种脚本注入(Script Injection)行为,所以也有一定的安全隐患.
    JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。

    2、window.name跨域

    indow对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因新页面的载入而进行重置。 
    数据大小有限制,大小一般为2M,IE和firefox下可以大至32M左右 
    有三个页面: 
    a.com/app.html:应用页面。 
    a.com/proxy.html:代理文件,一般是一个没有任何内容的html文件,需要和应用页面在同一域下。 
    b.com/data.html:应用页面需要获取数据的页面,可称为数据页面。 
    实现起来基本步骤如下:

    在应用页面(a.com/app.html)中创建一个iframe,把其src指向数据页面(b.com/data.html)。 
    数据页面会把数据附加到这个iframe的window.name上,data.html代码如下:

     
    1 <script type="text/javascript">
    2 
    3 window.name = 'I was there!'; // 这里是要传输的数据,大小一般为2M,IE和firefox下可以大至32M左右
    4 
    5 // 数据格式可以自定义,如json、字符串
    6 
    7 </script>

     

    在应用页面(a.com/app.html)中监听iframe的onload事件,在此事件中设置这个iframe的src指向本地域的代理文件(代理文件和应用页面在同一域下,所以可以相互通信)。app.html部分代码如下:

     
    1. <iframe src="http://gisbar.net/beta/d.html" style='display:none' frameborder="0" id="dataPage" onload ='loadFrame()'></iframe>

      <script type="text/javascript">


      function loadFrame(){
      var dataIframe = document.getElementById('dataPage');
      dataIframe.onload = function (){
      var data = dataIframe.contentWindow.name;
      console.log('window.name 跨域请求的数据:',data);
      }
      dataIframe.src = 'http://a.com/proxy.html';

      }

       </script>

    获取数据以后销毁这个iframe,释放内存;这也保证了安全(不被其他域frame js访问)。

     
    <script type="text/javascript">
    iframe.contentWindow.document.write('');
    iframe.contentWindow.close();
    document.body.removeChild(iframe);
    </script>

    总结起来即:iframe的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。 
    引自:http://www.cnblogs.com/rainman/archive/2011/02/21/1960044.html

     

    3、HTML5中新引进的window.postMessage方法跨域

    window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。

    调用postMessage方法的window对象是指要接收消息的那一个window对象,该方法的第一个参数message为要发送的消息,类型只能为字符串;第二个参数targetOrigin用来限定接收消息的那个window对象所在的域,如果不想限定域,可以使用通配符 * 。 
    缺点是IE6、IE7不支持

     在localhost页面中
    <iframe src="http://gisbar.net/beta/d.html" style='display:block' frameborder="1" id="msgFrame" onload ='loadMsgFrame()'></iframe>
    //postMessage跨域
     function loadMsgFrame(){
         var msgFrame = document.getElementById('msgFrame');
         msgFrame.contentWindow.postMessage('来自localhost的数据','http://gisbar.net/beta/');  //发送给指定域下的页面
     }    

    在http://gisbar.net/beta/d.html跨域页面中:

    window.onmessage = function(e){
        console.log('e',e);
        alert(e.data);   //来自localhost的数据
    }

    4、iframe+document.domain来跨子域

    我们只要把http://www.example.com/a.html 和 http://example.com/b.html这两个页面的document.domain都设成相同的域名就可以了。但要注意的是,document.domain的设置是有限制的,我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同。例如:a.b.example.com 中某个文档的document.domain 可以设成a.b.example.com、b.example.com 、example.com中的任意一个,但是不可以设成 c.a.b.example.com,因为这是当前域的子域,也不可以设成baidu.com,因为主域已经不相同了。

  • 相关阅读:
    js数组与字符串的相互转换方法
    js页面跳转常用的几种方式
    js刷新页面方法大全
    IIS上开启反向代理实现Vue项目接口跨域处理
    【问题解决记录】vue解决低版本安卓与ios10以下系统兼容性问题
    【解决问题记录】https网站中请求http资源接口报错与netERRSSLPROTOCOLERROR错误的解决
    indexedDb数据库基本操作
    Object常用方法
    htmlToTex
    禁止鼠标右键保存/拖动/选中/复制 图片/文字
  • 原文地址:https://www.cnblogs.com/lydialee/p/4037521.html
Copyright © 2011-2022 走看看