跨域实战解决方案

369 阅读3分钟

感知

明确:当从a网址发送异步请求b网址时,默认就会出现上述错误

术语:跨域

实战应用:

1 后端定义接口前端请求

2 请求第三方接口

3 A公司和B公司合作数据共享

等等都有可能出现跨域也就是上述报错

一、为什么会出现跨域问题

为了降低网站的安全风险,浏览器引入了同源策略,同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互,这是一个用于隔离潜在恶意文件的重要安全机制,同源策略必须确保“协议+域名+端口”三者都相同,即使两个不同的域名指向同一个ip地址,也不符合同源策略,不符合同源策略的请求即产生了跨域。但跨域并不是浏览器限制了请求,而是拒绝接受,也就是说请求会发送到服务器然后从服务器返回,但是浏览器拒绝接收。

二、什么是跨域

在前端领域中,

当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。

当前页面url			 被请求页面url			  是否跨域  原因
http://test.com/	http://test.com/a.html	  否	     同源(协议、域名、端口号相同)
http://test.com/	https://test.com/b.html	  跨域	协议不同(http/https)
http://test.com/	http://baidu.com/		  跨域	主域名不同(test/baidu)
http://w.test.com/	http://m.test.com/		  跨域	子域名不同(w/m)
http://test.com:81/	http://test.com:71/		  跨域	端口号不同(81/71)

脚下留心:跨域是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。

三、什么是同源策略

同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,它是由Netscape提出的一个著名的安全策略。

同源策略其主要限制以下几种行为:

1 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
2 无法接触非同源网页的 DOM
3 无法向非同源地址发送 AJAX 请求

四、跨域实战解决方案

前端:谷歌插件、前端代理、JSONP

后端:声明header头、后端代理

运维:服务器配置

其他:等等

五、使用

5.1 谷歌插件

vue、react项目都可以用

5.2 前端代理

前端代理一般是通过node中间件http-proxy-middleware实现的,在vue、react脚手架中,已经集成了该中间件,我们只需要配置使用既可。

devServer: {
    proxy: {
      '/api': {
        target: 'http://www.a.com', // 真实请求地址
        changeOrigin: true, // 默认false,是否需要改变原始主机头为目标URL
        secure: false,      // 关闭SSL证书验证https协议接口需要改成true
        ws: true,			// 是否代理websocket
        pathRewrite: {	    // 重写路径请求
             // 重写
             // '^/old/api' : '/new/api'
             // 移除
             // '^/remove/api' : ''
             // 添加
             // '^/' : '/basepath/'
        }
      },
    }
},

5.3 JSONP

服务端

handleCallback({"success": true, "user": "admin"})

客户端

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

// 接口地址
script.src = 'http://www.a.com/login?uname=admin&callback=handleCallback';
document.head.appendChild(script);

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

5.4 声明header头

node

app.all('*', function (req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');
    res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
    if (req.method == 'OPTIONS') {
        res.send(200);
    } else {
        next();
    }
});

其他语法:忽略

5.5 后端代理

问题:前端请求第三方接口出现跨域提示

解决:前端请求后端、后端请求第三方接口

5.6 服务器配置

server {

    // ...

    location / {
        root   html;
        index  index.html index.htm;
    }

    location /api/ {
        rewrite  ^/api/(.*)$ /$1 break;
        include  uwsgi_params;

        # ajax的url为/api/user/1的请求将会访问http://www.test.com/user/1
        proxy_pass   http://www.test.com;
   }

   // ...
}