1

1.什么是跨域

跨域指的的浏览器不能执行其它网站的脚本。它是由浏览器的同源策略导致的,是浏览器对js实施的安全措施。

2.什么是同源策略

同源指的是:url的协议、域名、端口均为相同
如果没有同源策略限制,浏览器很容易受到XSS、CSFR等攻击。
同源策略限制以下几种行为:
1.Cookie、LocalStorage 和 IndexDB 无法读取
2.DOM和JS对象无法获得
3.AJAX 请求不能发送

3.常见的跨域场景

以url:http://www.domain.com为对比:

url说明是否允许
http://www.domain.com/a.js协议域名都相同,不同文件允许
http://www.domain.com/b.js协议域名都相同,不同文件允许
https://www.domain.com/a.js协议不相同不允许
http://www.domain1.com/a.js主域名不相同不允许
http://xxx.domain.com/a.js子域名不相同不允许
http://www.domain.com:9000/a.js端口不相同不允许

4.跨域解决方案

4.1 JSONP

实现原理:利用script标签src属性中的链接却可以访问跨域的js脚本,服务端不再返回JSON格式的数据,而是返回一段调用一个函数的js代码,然后将数据作为参数传递了过来,在src中进行了调用,这样实现了跨域。由于这种方式传参,jsonp只能发送get请求。
示例代码:

 <script>
    let script = document.createElement('script');
    script.type = 'text/javascript';

    // 传参一个回调函数callback给后端,后端返回时执行这个在前端定义的回调函数并把数据传递过来
    script.src = 'http://localhost:9500/login?callback=handleCallback';
    document.head.appendChild(script);

    // 回调执行函数(接收数据)
    function handleCallback(res) {
      alert(JSON.stringify(res));
    }
  </script>

4.2 跨域资源共享(CORS)

CORS 全称 Cross-origin Resource Sharing 中文名称 “跨域资源共享” 它突破了浏览器只能发送同源请求向服务器获取数据的限制。

它允许浏览器向跨域服务器跨域,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

需要在服务端设置:
Access-Control-Allow-Origin 表示允许跨域的来源
Access-Control-Allow-Methods 表示允许跨域方法
Access-Control-Allow-Headers 表示允许接受的自定义header字段名
Access-Control-Max-Age 表示预检请求的结果能够被缓存多久,即在多久内可以省略 预检请求

4.3 nginx代理跨域

nginx代理跨域,实质和CORS跨域原理一样,通过配置文件请求响应头实现
静态文件设置跨域:

location / {
        root   /usr/share/nginx/html;
        try_files $uri $uri/ /index.html;
        index  index.html index.htm;
        # 使得html、js、css等文件可以跨域访问
        add_header Access-Control-Allow-Origin *;
    }

接口反向代理跨域

location ~* ^/(auth|function|admin){
    if ($request_method = 'OPTIONS') {
      add_header 'Access-Control-Allow-Origin' 'http://127.0.0.1:9500';
      add_header 'Access-Control-Allow-Methods' 'PUT,DELETE';
      add_header 'Access-Control-Allow-Headers' 'Test-CORS, Content-Type';
      add_header 'Access-Control-Max-Age' 1728000;
      add_header 'Access-Control-Allow-Credentials' 'true';
      add_header 'Content-Length' 0;
      return 204;
    }

    add_header 'Access-Control-Allow-Origin' 'http://127.0.0.1:9500';
    add_header 'Access-Control-Allow-Credentials' 'true';

    proxy_pass http://127.0.0.1:7000;
    proxy_set_header Host $host;
  }

4.4 document.domain + iframe跨域

此方案仅限主域相同,子域不同的跨域应用场景。
实现原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。
示例代码:

// 父子页面都设置document.domain为相同的域
<script>
    document.domain = 'domain.com';
</script>

4.5 location.hash + iframe跨域

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

4.6 postMessage跨域

postMessage是HTML5中为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:
1、页面和其打开的新窗口的数据传递
2、多窗口之间消息传递
3、页面与嵌套的iframe消息传递
4、上面三个场景的跨域数据传递

4.7 WebSocket协议跨域

WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯。


fuGUI
1.6k 声望1.9k 粉丝

The best time to plant a tree is ten years ago, and the second,let us start