聊一聊前端跨域

1、浏览器的同源策略:指不同域的客户端脚本在没明确授权的情况下,不能读写对方的资源。跨域指js在不同域(协议、域名、端口号有一处不同则属不同域)之间进行数据传输。

2、非同源会有以下三种行为受到限制:

(1) Cookie、LocalStorage 和 IndexDB 无法读取。

(2) DOM 无法获得。

(3) AJAX 请求不能发送。

 

3、针对以上三种行为的解决方案对应如下:

1)cookie无法获取:cookie是服务器写入浏览器的一小段信息,只有同源的网页才能共享。但是,两个网页一级域名相同,只是二级域名不同,浏览器允许通过设置document.domain共享 Cookie。

2)Dom无法获取:如果两个网页不同源,就无法拿到对方的DOM。典型的例子是iframe窗口和window.open方法打开的窗口,它们与父窗口无法通信。

    a、如果两个窗口一级域名相同,只是二级域名不同,那么设置上一节介绍的document.domain属性,就可以规避同源政策,拿到DOM。

    b、对于完全不同源的网站,目前有三种方法,可以解决跨域窗口的通信问题,分别是:片段标识符、window.name、跨文档通信API。

          i. 片段识别符(fragment identifier)

              定义:指的是URL的#号后面的部分,http://example.com/x.html#fragment的#fragment。如果只是改变片段标识                                       符,页面不会重新刷新。

              方法:父窗口可以把信息,写入子窗口的片段标识符。(反过来也可以)子窗口通过监听hashchange事件得到通                                    知。

          ii. window.name

             特点:浏览器窗口有window.name属性。这个属性的最大特点是,无论是否同源,只要在同一个窗口里,前一个网页设                          置了这个属性,后一个网页可以读取它。(父子窗口可通过设置此属性实现数据传输)

             优缺点:优点是,window.name容量很大,可以放置非常长的字符串;缺点是必须监听子窗口window.name属性的变                                 化,影响网页性能。

          iii. 跨文档通信API(Cross-document messaging): H5新增。允许跨窗口通信,不论这两个窗口是否同源。

              例子:

//发送方可以通过postMessage发送消息
var prop = window.open("http://bbb.com",title);
prop.postMessage("hello world!","http://bbb.com");


//接收方可通过添加message事件监听器进行监听
window.addEventListener("message",function(e){
    console.log(e.data);
},false)

             其他用途:通过此方式也可读取其他窗口的 LocalStorage 

3)AJAX请求无法发送:同源政策规定,AJAX请求只能发给同源的网址,否则就报错。有三种方法规避:JSONP、WebSocket、CORS。

        a、JSONP:本质是利用了标签具有可跨域的特性。由服务端返回预先定义好的javascript函数的调用,并且将服务端数据以该函数参数的形式传递过来。

前端代码:
<script>
       function fuc(data){
          console.log(data.name);
         }
</script>
<script src="http://www.baidu.com/api.php?callback=fuc"></script> 

后端代码:
<?php
     $cb = $_GET['callback'];
     $data = array(
                 'name'=> 'zs',
                 'age'=>18,
                 'gender'=>true
             );
     echo $cb.'('.json_encode($data).')';
 ?>    

   b、WebSocket:WebSocket是一种通信协议,不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。

           方式:浏览器发出的WebSocket请求的头信息中包括origin字段(发自哪个域名)。服务器可以根据这个字段,判断是否许可本次通信。     

   c、CORS:是跨源AJAX请求的根本解决方法。相比JSONP只能发GET请求,CORS允许任何类型的请求。只要服务器实现了CORS接口,就可以跨源通信。

         分类:简单请求、非简单请求。

只要同时满足以下两大条件,就属于简单请求:

           请求方法是以下三种方法之一:HEAD、GET、POST

           HTTP的头信息不超出以下几种字段:Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

                  i. 简单请求:浏览器直接发出CORS请求。

                         在头信息之中,增加一个Origin字段,服务器根据这个值,决定是否同意这次请 求。返回值有以下类型:

                            

                  ii. 非简单请求:

                        预检请求:非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(方法是options)

                        服务器的否定回应:浏览器否定了"预检"请求,会返回一个正常的HTTP回应,但是没有任何CORS相关的头信息字段。

                        服务器的通过回应:以后每次浏览器正常的CORS请求,就都跟简单请求一样,会有一个Origin头信息字段。服务器的回应,也都会有一个Access-Control-Allow-Origin头信息字段。

猜你喜欢

转载自blog.csdn.net/weixin_39963132/article/details/84303094