写个小记,记录一下关于跨域这件事
跨域问题的产生
跨域的问题,离不开一个关键词:同源策略。在mdn的描述中:同源策略是一个重要的安全策略
而在现在前后端分离的开发模式下,经常会因为前后端不同源而产生跨域问题。跨域问题就像是一道城墙,阻挡开发者们的信息交互,因此就有各种解决跨域的方案产生。
跨域的解决方式
关闭浏览器检测
浏览器实现了同源策略,对网站的所有请求都做了同源检测。检测不合格,即使是请求成功返回数据也是不予许访问数据。所以我们可以关闭浏览器的同源策略。具体办法就自己baidu啦。因为这种方法也就只能在自己本机开发的时候使用,这里也就不多做说明。
jsonp方式
jsonp的实现基于script的src属性不受同源策略的影响。前端动态插入script标签,并且将src属性指向实现了jsonp的接口,同时声明好前后端协调好的回调函数。回调函数会被后台直接在客户端调用,并传入数据。前端只需在函数中加入获取数据后的后续操作。 例如: 后端(node)
jsonpAction() {
const cb = this.get('callback');
if (think.isEmpty(cb)) {
this.fail(100, '缺少回调函数参数');
return;
}
const data = {
msg: 'jsonp数据'
};
this.body = `cb(${JSON.stringify(data)})`;
}
前端
let script = document.createElement('script');
script.src = 'protocol://domain/index/jsonp?callback=cb';
document.body.appendChild(script);
function cb(data) {
console.log('后台返回的数据', data);
}
jsonp的方式由于实现的过程限制,只能适用于get方式。
代理方式
代理的方式其实也很好理解。因为服务器和服务器之间的请求没有浏览器的这种同源策略,所以我们可以使用一个代理的服务器,前端请求代理的服务器,通过代理服务器去请求真正的数据源服务器。然后在获取到数据之后代理服务器在返回前端。绕过浏览器的检查。在vue脚手架搭建的开发环境中就有集成这样功能。想要了解的不妨看一下vue文档(通过webpack集成的中间件)
CORS方式
上面的jsonp和代理的方式都是通过绕过浏览器的检测来获取数据。而CORS方式则是通过告诉浏览器,允许不同源的数据被访问。其主要的就是http请求中的 Access-Control-Allow-Origin 这一个请求头。在服务器返回的http请求中设置这样的一个请求头,告诉浏览器,哪一些跨域请求可以被允许。例如:
corsAction() {
this.header('Access-Controle-Allow-Origin', '*');
}
上面的这段代码是在告诉浏览器说无论是任何的访问源来访问cors这个接口都被允许获取到数据,直接通过了浏览器的检测,允许了访问。这种方式相较于jsonp更为全面一些,即使是post请求也是被允许的,相较于代理的方式也来的更为的直接。但是这样的方式还是有缺点:
一、 服务器这样的设置,前端的任意访问源都被允许,安全性变差
二、 这样通配的方式在请求不允许携带cookie到后端去。
为了解决上面的问题,对代码做出一下的改动
corsAction() {
// 获取域名
let origin = this.header("origin");
if (think.isEmpty(origin)) {
const protocol = this.ctx.protocol;
const referer = this.referer(true);
origin = `${protocol}://${referer}`;
}
const host = origin.split('://')[1];
// 白名单列表
const whiteDomain = ['bbstage.jlinz.cn'];
let flag = false;
whiteDomain.forEach(domain => {
if (host === domain) flag = true;
})
if (flag) {
this.header("Access-Control-Allow-Origin", origin);
this.header("Access-Control-Allow-Headers", " Origin, X-Requested-With, Content-Type, Accept");
this.header('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS');
}
}
在上面的代码中,我们获取到了请求源的协议和域名,并且声明了一个白名单。我们将请求源的域名和白名单中的域名一一对比,如果白名单中有,我们就设置允许访问的请求头。在cors的方式中,我们只要指定了允许访问的域名,前端的访问就可以携带cookie到后端,我们也能控制那些请求源被允许访问。
以上,就是我对开发过程中遇到跨域的记录。有什么不对的,希望大家多多指点。thanks!