这篇文章主要用于记录自己平时开发遇到的cookie相关的问题. 如跨域设置cookie, cookie特殊字符被截断, 中文cookie导致报错.
如果对cookie不太了解, 推荐这篇文章, 很详细
浏览器系列之 Cookie 和 SameSite 属性
跨域设置cookie
这个场景一般是在账号打通中会遇到,两个系统使用同一个账号体系,但是不同的域名。登陆一个系统的时候自动登陆到另一个系统。例如在 a.com 下同时把 cookie 设置到 b.com 下。
一般的处理方式是:在登陆完成之后,返回另一个域的setCookieUrl和获取cookie的信息(可以是加密的cookie,或者是把cookie存入缓存返回key,保证随机且复杂的key,且过期时间尽可能短)。
然后再让前端发起另一个域的异步请求设置cookie。 (在 a 的域下请求 b 域的url并设置cookie)
但是对于 chrome80 之后的版本,chrome默认不支持跨域设置cookie。解决方式有两个:
-
引导用户设置浏览器支持三方cookie,以及在
chrome://flags
下面修改以下两项设置. 大概的做法就是:在登陆前,先发一个跨域设置cookie的请求,再发一个请求判断是否设置成功. 不成功就引导用户去修改浏览器设置.
-
在 cookie 中添加
SameSite=None; Secure
字段,且必须使用 https协议. 不能直接用 Cookie 类, Cookie无SameSite属性. 需手动在response header 中设置,如:
response.addHeader("Set-Cookie", "key=name; SameSite=None; Secure")
但是, 对于部分浏览器(如ios微信内置浏览器) 仍然不支持跨域设置cookie. 这个时候就只能先跳到相同的域名的中间页下面, 再请求setCookieUrl, 然后再回到之前的页面. 流程比上面要多一些.
cookie 包含特殊字符导致被截断
如:
header中: cookie:"key=value@1234"
然后使用 HttpServletRequest.getCookies 得到的cookie的则是key=value。实际上完整的value还是存在header中.
这个主要原因是使用了 LegacyCookieProcessor 作为 cookie处理器,value包含以下特殊字符会被截断。
// Excludes '/' since configuration controls whether or not to treat '/' as
// a separator
private static final char[] HTTP_SEPARATORS = new char[] {
'\t', ' ', '\"', '(', ')', ',', ':', ';', '<', '=', '>', '?', '@',
'[', '\\', ']', '{', '}' };
推荐一篇相关的文章: https://juejin.cn/post/6844903918330183694
看完这篇文章,我猜可能就是前面的人因为setCookie的时候在 domain 里面加了 .
才改成 LegacyCookieProcessor的, 但其实没必要, domain前面根本不用加.
.
解决方式:
- 不在cookie中使用特殊字符
- 不使用LegacyCookieProcessor。
- 自己从 request 的 header 读取 Cookie,然后自己解析
因为cookie是外部传来的, 不能修改cookie. 这里选择第三种方式, 影响范围小,风险最小.
private static List<Cookie> parseCookies(HttpServletRequest request) {
String cookieStr = request.getHeader("Cookie");
if (StringUtils.isEmpty(cookieStr)) {
return Collections.emptyList();
}
List<Cookie> cookies = new ArrayList<Cookie>();
String[] cks = cookieStr.split(";");
for (String ckStr : cks) {
try {
String[] ck = ckStr.trim().split("=", 2);
if (ck.length<2) continue;
Cookie cookie = new Cookie(ck[0], ck[1]);
cookies.add(cookie);
} catch (Exception e) {
log.error("parseCookies error.", e);
}
}
return cookies;
}
cookie 中有中文导致后端报错
cookie中最好不要用中文, 否则服务端可能处理不了导致报错. 具体原因也是上面那个 LegacyCookieProcessor 解析cookie时抛出的异常.
注意: 不仅自己不要使用中文cookie, 也要注意前端有没有给传中文cookie!