以前公司的项目,曾经遇到过cookie无法携带的问题,排查了很久。近日一个做前端的朋友也遇到了类似的问题,问起我来,想想这个问题也可以记录一下,于是便有了这篇文章。
首先,同域 请求时,cookie是可以自动携带的,出现cookie无法自动携带,往往就是跨域导致的。
一般现在都是前后端分离,因此一般都会有跨域的情况,往往cookie无法自动携带就是跨域问题导致的。
我认为遇到类似的问题(cookie无法自动携带)需要注意以下几点:
- 是否设置了
withCredentials
如果在发送来自其他域的XMLHttpRequest请求之前,未设置withCredentials 为true,那么就不能为它自己的域设置cookie值
一些常见的例子:
由于我最熟悉的是vue,用的最多的库是axios,因此特别拿出来先说:
// axios
// 一般而言,我们使用axios时都会封装一个项目的请求库(当然使用jq等也是一样,这里只是以axios举例),那写法应该是类似如下:
import axios from 'axios';
const http = axios.create({
withCredentials: true // 允许携带cookie
});
// 当然单独使用也是可以的,写法类似如下:
cons data = {}
axios.post('url',data,{
withCredentials: true // 允许携带cookie
});
// 原生ajax
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/', true);
xhr.withCredentials = true;
xhr.send(null);
// jquery
$.ajax({
method: 'get',
url: 'apiUrl',
xhrFields: {
withCredentials: true
}
})
// fetch
fetch(url, {
credentials: "include", // include, same-origin, omit
})
- 检查请求报文
确认后台的配置是否正确,这个可以通过查看请求的响应报文来判断。
如果是跨域请求,后端的请求是要配置cors的。这块后端具体要怎么写代码,我是不熟悉的,但是这并不影响我们进行判断。
首先请确认跨域请求是否正常,预检是否返回200。查看报文,复杂请求,在请求前还有一个options请求,看看他是否返回了200,如果没有就证明它的配置存在问题。
大体上后端涉及配置请求头如下:
Access-Control-Allow-Origin: <origin> | * // 授权的访问源
Access-Control-Max-Age: <delta-seconds> // 预检授权的有效期,单位:秒
Access-Control-Allow-Credentials: true | false // 是否允许携带 Cookie
Access-Control-Allow-Methods: <method>[, <method>]* // 允许的请求动词
Access-Control-Allow-Headers: <field-name>[, <field-name>]* // 额外允许携带的请求头
Access-Control-Expose-Headers: <field-name>[, <field-name>]* // 额外允许访问的响应头
我会重点留意
- Access-Control-Allow-Credentials是否配置了true
- Access-Control-Allow-Origin必须要配置,而且不能是*
尤其是第二点,很多时候,尤其是开发阶段,后端往往喜欢将Access-Control-Allow-Origin配置为*
,但是如果要携带cookie的话就不可以这样子配置了。
附带身份凭证的请求与通配符
对于附带身份凭证的请求,服务器不得设置 Access-Control-Allow-Origin 的值为“”。
这是因为请求的首部中携带了 Cookie 信息,如果 Access-Control-Allow-Origin 的值为“”,请求将会失败。而将 Access-Control-Allow-Origin 的值设置为 http://foo.example,则请求将成功执行。
注意:这个图片的配置就是典型的错误
补充一句提问话:当时我遇到的cookie无法携带的问题,其中一个原因就是后台配置Access-Control-Allow-Credentials
时错误配置了两个true
。。。
所以,请一定要仔细比对报文,看清楚是否有异常的地方
会不会,走完了以上的流程还是无法解决问题呢?我无法排除这种可能。
我相信,仔细检查完以上两步是可以解决绝大部分cookie无法自动携带问题的(请确保你自身已经仔细的排除了以上两点原因),但凡事总有意外。
最近我吸取了一个教训,要用经验解决问题也许可以提高效率,但有时反而会蒙蔽了自己的眼睛,而对真相视而不见。也许问题的原因是你自身万万没想到的。我的建议是遇到这种请求,请审视一下,自身是否有什么假设,而将真相排除在外了,这一点很重要,尤其是你已经束手无策的时候!
例如,会不会真的是浏览器的问题,会不会这个版本存在缺陷等。我知道一般这种概率比较低,但真的请不要轻易将低概率事件和不可能发生等同起来。考虑重启电脑,更换设备的方法。
以上是我的建议,不过,关于cookie无法携带,我还是可以想到一些其他的可能的,也许你可以再依据这些去排查一下:
- 浏览器是可以禁用cookie的,请确认一下你的浏览器有没有禁用了cookie,或者是否设置了阻止外部所有cookie
- 你的浏览器是不是装了许多插件,会不会是你的插件导致的问题
- 你有没有用什么工具模拟请求,会不会是其中的设置有问题
- cookie其实还有一些属性的,例如domain、path、失效时间、大小等。其中,path有设置什么值吗?如果设置了就只会向指定路径发送cookie了
- 还有一点,后台返回的cookie是有可能被浏览器隐藏无法在控制台显示的,你可以在这里确认cookie是否已经设置了
好,以上就是我对cookie无法自动携带问题的整理,希望能帮助到你