在Http浅析【2】——ajax跨域问题中对跨域产生的原因和解决方法做了说明。这一章节,把带cookie的跨域问题单独拎出来。
带cookie的跨域
随着项目模块越来越多,很多模块现在都是独立部署。模块之间的交流有时可能会通过cookie来完成。比如说门户和应用,分别部署在不同的机器或者web容器中,假如用户登陆之后会在浏览器客户端写入cookie(记录着用户上下文信息),应用想要获取门户下的cookie,这就产生了cookie跨域的问题。
当出现带cookie的跨域问题时,浏览器会报如下错误:
即*无法满足带cookie的情景,如下的配置方法肯定是错误的
如果把header改为特定的地址
res.addHeader("Access-Control-Allow-origin","http://localhost:8081");
则可能会出现如下错误:
接下来我们继续设置,在服务端添加允许证书的配置:
//enable cookie
res.addHeader("Access-Control-Allow-Credentials","true");
同时在客户端也进行相关设置:
但随之而来的问题也比较明显,那就是我们显然不能把origin里的地址写死,所以我们需要在http请求中取出orign字段,然后设置在响应头当中。
这样就完成了带cookie的跨域调用。这里再总结一下:
【1】带cookie的跨域时,Access-Control-Allow-Origin 不能设置为*
【2】发送的cookie的被调用发(服务器)的cookie,而不是调用方(浏览器)的cookie
前台fetch+后台node+express
前台请求封装request
export default function request(url, options) {
const defaultOptions = {
};
const newOptions = { ...defaultOptions, ...options };
if (newOptions.method === 'POST' || newOptions.method === 'PUT') {
if (!(newOptions.body instanceof FormData)) {
newOptions.headers = {
'Content-Type': 'application/json; charset=utf-8',
...newOptions.headers,
};
newOptions.body = JSON.stringify(newOptions.body);
//newOptions.body = newOptions.body;
} else {
// newOptions.body is FormData
newOptions.headers = {
Accept: 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
...newOptions.headers,
};
}
}
return fetch(url,newOptions)
.then((response) => {
if (newOptions.method === 'DELETE' || response.status === 204) {
return response.text();
}
return response.json();
})
}
前台请求
request(loginApi, {
method: 'POST',
body: {user: values},
mode: 'cors',
credentials: 'include',
// cookie: localStorage.cookie
})
.then(result => {
if (!result) {
Feedback.toast.error('登录失败,请稍后再试:err-result为null-系统错误');
return
}
if (result.status === 200) {
Feedback.toast.success('登录成功');
//保存用户的session
localStorage.cookie = result.cookie
this.props.history.push('/home');
return
} else {
Feedback.toast.error('登录失败,请稍后再试:err' + result.statusText);
return
}
})
后台node+express跨域设置
//跨域设置
app.all('*', function (req, res, next) {
const origin = req.headers.origin //动态获取origin
res.header("Access-Control-Allow-Origin", origin);
res.header("Access-Control-Allow-Credentials", "true");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By", ' 3.2.1')
next();
})
若有疑问可以QQ联系笔者,虽然不一定100%解决你的问题,但是可以交流探讨一波:2276604211