一, 前言
今天遇到一个坑, 浏览器请求数据的时候 gg 了. 浏览器报错如下图:
因为请求头部设置了 credentis mode is 'include', 从上面可以看出是 Access-Control-Allow-Credentials 这个响应必须设置为 true.
二, 思考
第一反应前端没有设置过这个值啊? 应该走默认才对吧? 测试环境 OK 啊!
--------------------------------- 真是一万只野马狂奔而过啊 -------------------------------------
由于之前没有遇到过这个问题, 对这个也没怎么关注, 所以排错慢了点.
后面查了一下资料, 然后回归一下代码, oh my god! 其他前端宝宝在请求中设置了这个:(因为是合作开发, 我也没有注意这个, 此处没有甩锅的 ys)
config.withCredentials = true
那么前端设置上面这个有啥用? 那为什么加了就报错呢? 后台难道没有配合设置对应相应头部吗?
[后续想起] 估计是后台小哥哥说过:"前端最好给后台传 cookie 和 token" 这句话吧, 导致前端小哥哥加上了这个设置, 不过后面后台并没有设置 cookie. 所以没必要加啊, 这就是信息不对称导致结果吧.
三, 原理及处理方法
1, 标准的跨域请求是不会发送 cookie 等用户认证凭据的, XMLHttpRequest 2 的一个重要改进就是提供了对授信请求访问的支持. 也就是说, 如果发生跨域请求, 又想携带 cookie 到服务器, 前端请求和后端响应都必须设置:
2, 前端请求:
- var xhr = new XMLHttpRequest();
- xhr.open('GET', 'http://www.xxx.com/api');
- xhr.withCredentials = true;
- xhr.onload = onLoadHandler;
- xhr.send();
或者在 axios 请求配置中设置:
3, 服务端响应头:
Access-Control-Allow-Credentials: true
如果服务端不设置该响应头, 浏览器会报错, 当然响应会被忽略不可用;
同时, 服务端需指定一个域名 (Access-Control-Allow-Origin:www.xxx.com), 而不能使用泛型(Access-Control-Allow-Origin: *) 不然即使设置了该头部, cookie 开始不能转到服务器.
四, 总结
1, 本次错误是因为前端配置了 Credentials:true, 但是浏览器没有设置 Access-Control-Allow-Credentials: true, 且响应是 Access-Control-Allow-Origin:*;
2, 如果在跨域中希望浏览器能携带 cookie 到服务器, 前后端都应该设置 Credentials 的值为 true, 且 Access-Control-Allow-Origin 就不能设为星号, 必须指定明确的, 与请求网页一致的域名., 不然 cookie 还是不能携带过去;
3,Cookie 依然遵循同源政策, 只有用服务器域名设置的 Cookie 才会上传, 其他域名的 Cookie 并不会上传, 且 (跨源) 原网页代码中的 document.cookie 也无法读取服务器域名下的 Cookie;
4, 如果服务器不要浏览器发送 cookie, 前后端都不设置这个字段就好了.
来源: http://www.bubuko.com/infodetail-2647467.html