关于前端跨域处理的方法总结

2017-10-29  本文已影响0人  R_JsBest

前端跨域的那些总结

做项目期间一直有遇到关于跨域方面的问题,之前由于没有上过生产环境,对于这方面的问题还不够全面,只是在前后端分离的方面遇到过,还是本地环境,主要是基于JSONP解决的;在最近的Vue项目中遇到的本地开发环境的跨域解决临时使用了dev中的index.js配置文件下内置的proxyTable属性配置解决跨域,测试环境行的通,但是生产环境则不行,会踩到这,还是对跨域不够清楚,最后重新复习了关于跨域方面的知识,对于线上环境配置了nginx反向代理后解决了跨域问题;下面,总结下对于跨域的认识。

在我们的浏览器中有一条策略叫做“同源策略”,什么叫同源策略呢?也就是当我们前后端数据交互的时候,如果两个页面所处的端口或者子域名以及通信协议中的任何一个不同,那么当你需要在违反同源策略的情况下在两个页面间通信时,就会出现跨域错误,因为浏览器出于安全考虑,限制了此类访问操作;但是日常开发操作中对于跨域操作的使用非常频繁,所以如何解决此类限制,完成不同页面间的数据通信,就是我们学习跨域操作及其工作原理的原因。

 ``` javascript
    <iframe src="https://www.baidu.com/request.html">
    <script>
         document.domain = " baidu.com " //这里是将A中的document.domain设置成主域
     </script>
  
<iframe src="https://baidu.com/response.html">
<script>
    document.domain = "baidu.com" //B页面的document.domain设置相同的domain即可
</script>

 // 但是,此类解决办法只适用于不同子域的框架间的交互。
  ```

2、location.hash

场景:对于页面中有iframe的页面中,父窗口可以对iframe的url进行读写。而在URL上有一部分#加上后面的字符可以用来进行锚点定位,这部分就是这里会提到的hash。利用修改URL的hash部分可以进行双向通信,从而达到跨域的目的,每个window通过改变其他window的location来发送消息,其他窗口通过监听URL的变化来接受消息,这个方式的通信会造成一些不必要的浏览器历史记录,而且有些浏览器不支持onhashchange事件,需要通过轮询操作来获取URL的改变,最后,这样做也存在一定问题,就是不仅数据会直接暴露在url中,数据容量和类型都有限。

示例:假如当前父页面' baidu.com/request.html ',其中嵌入的页面是’ xupt.edu.cn/response.html ‘,要实现此两个页面间的通信可以通过以下方法。

> 1.request.html传送数据到 response.html , request.html下修改为iframe的src为 'xupt.edu.cn/response.html'

>2.response.html监听到相应数据发生变化,触发对应操作。

>3.response.html传送数据到 request.html 中,但是由于两个页面不在同源下,会受到限制,所以要借助父窗口域名下的一个代理iframe。

>4.request.html下创建一个隐藏的iframe, 此Iframe的src是baidu.com域下的,并挂上要传送的hash数据;如 src = "baidu.com/proxy.html"

>5.proxy.html监听到URL变化,修改a.html变化的URL,由于二者是同源,所以在proxy.html中可修改a.html的url hash

>6.request.html监听到url变化,触发相应操作。
    // request.html 简单处理代码
    try{
        parent.location.hash = 'data';
    }catch(e){
        // ie Chrome存在安全机制,所以无法修改 parent.location.hash
        var _proxy = document.createElement('iframe');
        
        _proxy.style.display = 'none';
        _proxy.src = 'baidu.com/proxy.html';
    }
    
    // proxy.html关键代码处理
    // 由于proxy.html和baidu.com/request.html存在与同域,所以可以正常改变其location.hash的值。
    
    parent.parent.location.hash = self.location.hash.substring(1);

3、Html5的 postMessage( )
场景:该属性各大主流浏览器均支持,主要是包括接收信息的方法和发送信息的postMessage方法,比如A页面通过内嵌Iframe,获取一个B页面,就可以通过此方法实现A页面和B页面的通信。

    // A页面通过 postMessage() 发送消息
    window.onload = function (){
        var _iframe = document.getElementById('ifr');  
        var targetOrigin = "https://www.google.com";  
        _iframe.contentWindow.postMessage('hello world!', targetOrigin);
    }
    
    // 在B页面通过监听 message 事件并接收消息
    var onmessage = function (event){
      var data = event.data;//消息  
      var origin = event.origin;//消息来源地址  
      var source = event.source;//源Window对象  
      if(origin=="https://www.baidu.com"){  
        console.log(data);//hello world!  
      }  
    };
    
    if (typeof window.addEventListener != 'undefined') {  
      window.addEventListener('message', onmessage, false);  
    } else if (typeof window.attachEvent != 'undefined') {  
      //IE浏览器需要做特殊处理
      window.attachEvent('onmessage', onmessage);  
    }  

5、通过JSONP跨域
场景:通过script标签引入的JS不回受到浏览器同源策略的限制,所以我们可以通过生成的script标签引入一个JS或者其他后缀形式的文件,但是这些文件返回的是一个JS函数的调用。
> 如果作为一个JS文件引入,那么接口或请求地址返回的必须是一个可以执行的JS文件,这里需要在编写的时候和后端约定好规范。

6、通过CROS跨域
场景:CROS全称是跨域资源共享,定义了必须在访问跨域资源时浏览器与服务器应该如何沟通,CROS背后的基本思想就是使用自定义的HTTP头部让浏览器与服务器进行数据通信,主流浏览器均支持该功能,但是IE浏览器版本不能低于IE10。并且,使用此方法的关键在于服务器的配置处理,只要服务器实现了CORS接口,就可以实现跨域通信。

在服务端里面,对于CROS的支持,主要是通过设置响应头Access-Control-Allow-Origin来进行,如果浏览器监测到相应的设置,就可以允许跨域通信请求。
上边提到的JSONP实现跨域,有很大的局限性,只支持GET请求,但是在CROS实现的跨域请求访问中,支持所有的数据请求方式,并且有更好的错误处理方式,能够接收简单的XMLHttpRequest发起的请求。

7、设置Window.name属性
场景: 每个window对象有个name属性,该属性有个特征:在一个创口的生命周期之内,窗口载入的所有页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的,并不会因为新页面的载入而进行重置;并且,由于安全原因限制,浏览器始终都会保持window,name是 string 类型。

这种方法与document.domain相比,放宽了域名后缀要相同的限制,可以从任意页面获取string类型的数据。

8、配置反向代理服务器
场景:基本解决思路就是将其服务所在的服务器配置成所需的跨域资源访问的反向代理服务器,在nginx服务器配置上,将当前接收到需要发送的各类请求链接,按照实际需要,配置好转发规则,通过服务器处理相应的请求链接,对于浏览器来说,这些请求是发送到本机服务器的,是同源的,而实际请求是又服务器进行转发,这样就不会触及浏览器的同源策略限制,就能实现正常的跨域通信请求等操作。

上一篇 下一篇

猜你喜欢

热点阅读