浅谈Koa2框架利用CORS完成跨域ajax请求

2020-06-17 07:00:54易采站长站整理

为了便于后续的检测,我们预先在http://127.0.0.1:3001这个域名下设置两个cookie。注意不要错误把cookie设置成中文(刚才我就设置成了中文,结果报错,半天没找到出错原因)

然后我们要做两步,第一步设置响应头Access-Control-Allow-Credentials为true,然后在客户端设置xhr对象的withCredentials属性为true。

客户端代码如下:


$.ajax({
type: 'put',
url: 'http://127.0.0.1:3001/put',
data: {
name: '黄天浩',
age: 20
},
xhrFields: {
withCredentials: true
}
}).done(data => {
console.log(data);
});

服务端如下:


app.use(async (ctx, next) => {
ctx.set('Access-Control-Allow-Origin', 'http://localhost:3000');
ctx.set('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET');
ctx.set('Access-Control-Allow-Credentials', true);
await next();
});

这时就可以带着cookie到服务器了,并且服务器也可以对cookie进行改动。但是cookie仍是http://127.0.0.1:3001域名下的cookie,无论怎么操作都在该域名下,无法访问其他域名下的cookie。

现在为止CORS的基本功能已经都提到过了。

一开始我不知道怎么给Access-Control-Allow-Origin,后来经人提醒,发现可以写一个白名单数组,然后每次接到请求时判断origin是否在白名单数组中,然后动态的设置Access-Control-Allow-Origin,代码如下:


app.use(async (ctx, next) => {
if (ctx.request.header.origin !== ctx.origin && whiteList.includes(ctx.request.header.origin)) {
ctx.set('Access-Control-Allow-Origin', ctx.request.header.origin);
ctx.set('Access-Control-Allow-Methods', 'PUT,DELETE,POST,GET');
ctx.set('Access-Control-Allow-Credentials', true);
ctx.set('Access-Control-Max-Age', 3600 * 24);
}
await next();
});

这样就可以不用*通配符也可匹配多个origin了。

注意:ctx.origin与ctx.request.header.origin不同,ctx.origin是本服务器的域名,ctx.request.header.origin是发送请求的请求头部的origin,二者不要混淆。

最后,我们再稍微调整一下自定义的中间件的结构,防止每次请求都返回Access-Control-Allow-Methods以及Access-Control-Max-Age,这两个响应头其实是没有必要每次都返回的,只是第一次有预检的时候返回就可以了。

调整后顺序如下:


app.use(async (ctx, next) => {
if (ctx.request.header.origin !== ctx.origin && whiteList.includes(ctx.request.header.origin)) {
ctx.set('Access-Control-Allow-Origin', ctx.request.header.origin);
ctx.set('Access-Control-Allow-Credentials', true);