美文网首页
同源策略和跨域

同源策略和跨域

作者: mingzihhh | 来源:发表于2019-01-14 20:57 被阅读0次

    同源策略

    • 浏览器出于安全方面的考虑,只允许与本域下的接口交互。不同源的客户端脚本在没有明确授权的情况下,不能读写对方的资源。

    • 同协议,同域名,同端口

    • 需要注意的是: 对于当前页面来说页面存放的 JS 文件的域不重要,重要的是加载该 JS的页面所在什么域,即代码的执行环境。对比当前页面的url和ajax请求的url。

    • 同源策略限制以下几种行为:

      1.) Cookie、LocalStorage 和 IndexDB 无法读取
      2.) DOM 和 Js对象无法获得
      3.) AJAX 请求不能发送
      

    跨域

    • 即绕过同源策略去获取数据

    • 广义的跨域:

    1.) 资源跳转: A链接、重定向、表单提交
    2.) 资源嵌入: <link>、<script>、<img>、<frame>等dom标签,还有样式中background:url()、@font-face()等文件外链
    3.) 脚本请求: js发起的ajax请求、dom和js对象的跨域操作等
    

    跨域解决方案

    JSONP(JSON with padding)
    • HTML 中 script,img标签这样获取资源的标签是没有跨域限制的,比如我们经常引入一个其他域下线上cdn的jQuery。
    • 实现:JSONP是通过 script 标签加载数据的方式去获取数据当做 JS 代码来执行。提前在页面上声明一个函数,函数名通过接口传参的方式传给后台,后台解析到函数名后在原始数据上「包裹」这个函数名,发送给前端。换句话说,JSONP 需要对应接口的后端的配合才能实现。
    • 缺点:JSONP只能发GET请求,因为本质上script加载资源就是GET

    前端实现:

          document.querySelector('.show').addEventListener('click',function(){
                var script = document.createElement('script');
                script.src = 'http://127.0.0.1:8080/getWeather?callback=showData';
                document.head.appendChild(script);
                document.head.removeChild(script);
            })
    

    后端部分代码:

     case '/getWeather':
                var weather = [
                    '北京:晴',
                    '杭州:阴',
                    '上海:多云'
                ]
                res.setHeader('Content-Type','text/json;charset=utf-8')
                if(pathObj.query.callback){
                    res.end(pathObj.query.callback + '(' + JSON.stringify(weather) + ')')
                }
                else{
                     res.end(JSON.stringify(weather))
    
                }  
                break;
    
    CORS
    • CORS 全称是跨域资源共享(Cross-Origin Resource Sharing),是一种 ajax 跨域请求资源的方式,支持现代浏览器,IE支持10以上。
    • 实现:当你使用 XMLHttpRequest 发送请求时,浏览器发现该请求不符合同源策略,会给该请求加一个请求头:Origin,后台进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin; 浏览器判断该响应头中是否包含 Origin 的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据。所以 CORS 的表象是让你觉得它与同源的 ajax 请求没啥区别,代码完全一样。
    • 普通跨域请求只需要服务端设置Access-Control-Allow-Origin即可,前端无须设置;若要带cookie请求:前后端都需要设置。

    前端实现:

            document.querySelector('.show').addEventListener('click',function(){
                var xhr = new XMLHttpRequest();
                xhr.open('GET','http://127.0.0.1:8080/getWeather',true);
                xhr.onload = function(){
                    if((xhr.status>=200&&xhr.status<=300)||xhr.status==304) { 
                        showData(JSON.parse(xhr.responseText)); 
                    }else{ 
                        console.log('error'); 
                    }
                } 
                xhr.onerror=function(){ 
                    console.log('error'); 
                } 
                xhr.send();
            })
    

    后端部分代码:

    case '/getWeather':
                var weather = [
                    '北京:晴',
                    '杭州:阴',
                    '上海:多云'
                ]
                res.setHeader('Access-control-Allow-Origin','http://a.com:8080')
                res.end(JSON.stringify(weather))
    
                break;
    
    
    降域: document.domain + iframe跨域
    • 仅限主域相同,子域不同的跨域应用场景。

    • 实现原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。

    postMessage跨域
    • postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:
      a.) 页面和其打开的新窗口的数据传递
      b.) 多窗口之间消息传递
      c.) 页面与嵌套的iframe消息传递
      d.) 上面三个场景的跨域数据传递

    • 用法:postMessage(data,origin)方法接受两个参数

      • data: html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用JSON.stringify()序列化。
      • origin: 协议+主机+端口号,也可以设置为"*",表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。
    • window.postMessage() 方法被调用时,会在所有页面脚本执行完毕之后(e.g., 在该方法之后设置的事件、之前设置的timeout 事件,etc.)向目标窗口派发一个 MessageEvent (一个事件)消息。 该MessageEvent消息有四个属性需要注意:

      • message 属性表示该message 的类型
      • data 属性为 window.postMessage()的第一个参数
      • origin 属性表示调用window.postMessage() 方法时调用页面的当前状态
      • source 属性记录调用 window.postMessage() 方法的窗口信息。

    以上具体实现见https://github.com/mingzihhh/cross-domain-demo

    参考资料:

    https://segmentfault.com/a/1190000011145364

    MDN文档

    相关文章

      网友评论

          本文标题:同源策略和跨域

          本文链接:https://www.haomeiwen.com/subject/dqfsdqtx.html