這篇文章主要用於記錄自己平時遇到的cookie相關的問題. 如跨域設置cookie, cookie特殊字符被截斷, 中文cookie導致報錯.
跨域設置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!