跨域

1/28/2021 Javascript

# 跨域

浏览器具有同源策略。所谓同源是指'协议、域名、端口'三者都相同,其中一个不相同,都是不同源。 同源策略限制以下行为: (1)Cookie、LocalStorage 和 IndexDB 无法读取 (2)DOM 和 JS 对象无法获得 (3)Ajax 请求不能发送

# 解决方法

  • JSONP 跨域 原理:利用 script 标签没有跨域限制,通过标签 src 属性,发送带有回调函数的 GET 请求,服务端将接口返回的数据拼凑到回调函数中,返回给浏览器,前端可以在回调函数中拿到返回的数据。
<script>
    var script = document.createElement('script');
    script.type = 'text/javascript';

    // 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数
    script.src = 'http://www.domain2.com:8080/login?user=admin&callback=handleCallback';
    document.head.appendChild(script);

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

 // 服务端返回
 handleCallback({"success": true, "user": "admin"})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  • 跨域资源共享 全称是"跨域资源共享"(Cross-origin resource sharing),允许浏览器向跨源服务器发送 XMLHttpRequest 请求。CORS 需要浏览器和服务器同时支持。 简单请求:

    1. 使用的请求方法以下之一:get、post、head

    2. 请求的 header 是:Accept、Accept-Language、Content-Language、Content-Type【application/x-www-form-urlencoded、multipart/form-data、text/plain】

    浏览器:在请求头中增加 Origin 字段 服务端响应头:

    1. Access-Control-Allow-Origin,必填,要么是*【接收任意域名】,要么是请求的 origin 的值 2. Access-Control-Allow-Credentials,表示是否允许发送 Cookie 3. Access-Control-Expose-Headers,如果需要拿到除去(Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma)的字段,需要定义

非简单请求:

  1. 请求的方法是 put 或者 delete 等
  2. Content-Type 字段的类型是 application/json 正式通信之前:有一次 HTTP 查询请求,称为'预检'请求,请求方法是 OPTIONS。请求头里,特殊字段有,Origin、Access-Control-Request-Method【必选,列出浏览器的 CORS 请求用到的方法】、Access-Control-Request-Headers【指定浏览器 CORS 请求会额外发送的头信息字段】 预检请求的回应:
  3. Access-Control-Allow-Methods:必选 逗号分隔的一个字符串,返回的所有支持的方法
  4. Access-Control-Allow-Headers: 表明服务器支持的所有头信息字段
  5. Access-Control-Allow-Credentials:表示是否允许发送 Cookie
  6. Access-Control-Max-Age:可选,用来指定预请求的有效期
  • nginx 代理跨域
#proxy服务器
server {
    listen       81;
    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;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

vue 项目中 webpack + webpack-dev-server,修改 webpack.config.js 配置

module.exports = {
    entry: {},
    module: {},
    ...
    devServer: {
        historyApiFallback: true,
        proxy: [{
            context: '/login',
            target: 'http://www.domain2.com:8080',  // 代理跨域目标接口
            changeOrigin: true,
            secure: false,  // 当代理某些https服务报错时用
            cookieDomainRewrite: 'www.domain1.com'  // 可以为false,表示不修改
        }],
        noInfo: true
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  • postMessage 跨域 postMessage(data,origin)方法接受两个参数: (1)data:支持任意类型或可复制的对象,建议传参时用 JSON.stringfy()序列化 (2)origin:协议+主机+端口号,也可以设置为"*",如果要指定和当前窗口同源的话设置为"/"。
上次更新: 3/22/2021, 3:28:01 PM