跨域原理及解决方案

目录

  • 1. 跨域原理
    • 1. 定义
    • 2. 同源策略(SOP,Same-Origin-Policy)
    • 3. 同源策略限制内容
    • 3. 允许跨域加载资源的标签
  • 2. 常见跨域场景
  • 3. 跨域解决方案
    • 1. JSONP(JSON with Padding(填充))
    • 2. 跨域资源共享(CORS,Cross-Origin Resource Sharing)
    • 3. PostMessage
    • 4. WebSocket
    • 5. Node中间件代理(两次跨域)
    • 6. Nginx反向代理
    • 7. window.name + iframe
    • 1. 实现原理
    • 2. window.name实现
    • 8. location.hash + iframe
    • 9. document.domain + iframe
    • 10. 总结
  • 4. 参考

1. 跨域原理

1. 定义

当协议、子域名、主域名、端口号中任意一个不相同时,都算作不同域。不同域之间相互请求资源,称为"跨域"

跨域原理及解决方案_第1张图片

2. 同源策略(SOP,Same-Origin-Policy)

  1. 同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。
  2. 同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。

3. 同源策略限制内容

  • Cookie、LocalStorage、IndexedDB 等存储性内容
  • DOM 节点
  • AJAX 请求不能发送

3. 允许跨域加载资源的标签

1.  
2.  
3. 

远程的getRemoteData.js

getRemoteData({
    code:0,
    result:'success'
});

后台search.php

6. JSONP请求流程图

跨域原理及解决方案_第2张图片

7. jQuery的JSONP形式

JSONP都是GET和异步请求的,不存在其他的请求方式和同步请求,且jQuery默认就会给JSONP的请求清除缓存。

7. ajax与jsonp区别

  1. ajax和jsonp这两种技术在调用方式上“看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装;
  2. ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是通过HTTP来动态添加
    b.html
    
    window.onmessage = function(e) { 
       console.log(e.data) //你好
       e.source.postMessage('hello', e.origin) 
    } 

    4. WebSocket

    1. 定义

    • WebSocket是HTML5的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。
    • WebSocket是应用层协议,基于 TCP 协议。
    • WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 server 与 client 都能主动向对方发送或接收数据。
    • WebSocket 在建立连接时需要借助 HTTP 协议,连接建立好了之后 client 与 server 之间的双向通信就与 HTTP 无关了。

    2. WebSocket实现跨域

    原生WebSocket API使用起来不太方便,可以使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。

    5. Node中间件代理(两次跨域)

    1. 实现原理

    同源策略是浏览器需要遵循的标准,而如果是服务器向服务器请求则无需遵循同源策略。
      - 接受客户端请求 。
      - 将请求 转发给服务器。
      - 拿到服务器 响应 数据。
      - 将 响应 转发给客户端。

    2. 流程图

    跨域原理及解决方案_第3张图片

    6. Nginx反向代理

    1. 实现原理

    通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域访问

    2. nginx配置

    // proxy服务器 
    server { 
        listen       80; 
        server_name  www.domain1.com; 
        location / { 
            proxy_pass   http://www.domain2.com:8080;  #反向代理 
            proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名 
            index  index.html index.htm; 
     
            # 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用 
            add_header Access-Control-Allow-Origin http://www.domain1.com;  #当前端只跨域不带cookie时,可为* 
            add_header Access-Control-Allow-Credentials true; 
        } 
    } 
    // index.html 
    var xhr = new XMLHttpRequest(); 
    // 前端开关:浏览器是否读写cookie 
    xhr.withCredentials = true; 
    // 访问nginx中的代理服务器 
    xhr.open('get', 'http://www.domain1.com/?user=admin', true); 
    xhr.send(); 

    7. window.name + iframe

    1. 实现原理

    通过window.name属性实现:name值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)

    2. window.name实现

    // a.html(http://example.com:8000/b.html) 
     
     

    b.html为中间代理页,与a.html同域,内容为空

    // c.html(http://example.com:9000/c.html) 
     

    总结:通过iframe的src属性由外域转向本地域,跨域数据即由iframe的window.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。

    8. location.hash + iframe

    1. 实现原理

    a.html与c.html跨域相互通信,通过中间页b.html来实现。 三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接js访问来通信。

    2. 具体实现步骤

    a.html和b.html是同域的,都是http://example.com:8000;而c.html是http://example.com:9000

    1. a.html给c.html传一个hash值,
    2. c.html收到hash值后,把hash值传递给b.html
    3. b.html将结果放到a.html的hash值中

    2. 具体实现步骤

    // a.html 
     
     
    
    
    // b.html 
     
     
     
     // c.html 
    console.log(location.hash); 
    let iframe = document.createElement('iframe'); 
    iframe.src = 'http://example.com:8000/b.html#hello'; 
    document.body.appendChild(iframe); 

    9. document.domain + iframe

    1. 实现原理

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

    该方式只能用于二级域名相同的情况下,比如 a.test.com 和 b.test.com 适用于该方式。 只需要给页面添加 document.domain ='test.com' 表示二级域名都相同就可以实现跨域。

    2. 具体实现步骤

    // 页面a.example.com:8000/a.html获取页面b.example.com:8000/b.html中a的值。
    
    // a.html 
     
        helloa
         
         
    
    
    
    // b.html 
     
        hellob 
         
     

    10. 总结

    • CORS支持所有类型的HTTP请求,是跨域HTTP请求的根本解决方案
    • JSONP只支持GET请求,JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。
    • 不管是Node中间件代理还是nginx反向代理,主要是通过同源策略对服务器不加限制实现跨域
    • 日常工作中,用得比较多的跨域方案是cors和nginx反向代理

    4. 参考

    • 九种跨域方式实现原理(完整版)
    • js中几种实用的跨域方法原理详解
    • jsonp 跨域原理分析
    • HTTP访问控制(CORS)
    • 跨域资源共享 CORS 详解

转载于:https://www.cnblogs.com/yueyun00/p/10782343.html

你可能感兴趣的:(跨域原理及解决方案)