问题: 66版本以上的谷歌游览器,默认Cookie的 SameSite 属性为Lax,导致无法跨域传输cookie
SameSite 有3个值
1. Strict
Strict
最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie。
2. Lax
Lax
规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。
3. None
Chrome 80版本后将Lax
变为默认设置。这时,网站可以选择显式关闭SameSite
属性,将其设为None
。不过,前提是必须同时设置Secure
属性(Cookie 只能通过 HTTPS 协议发送),否则无效。
所以当我们需要跨域传输cookie时就必须设置SameSite=None;Secure=true
但是问题来了,当我们设置为SameSite=None;Secure=true后发现,51-66版本的谷歌无法正常使用cookie了,原因是这些版本的
SameSite属性并没有None值
解决方案
在写入cookie时判断游览器版本 再设置cookie的SameSite值
判断游览器版本获取SameSite值
public static String getSameSize (HttpServletRequest request){
String userAgent = request.getHeader("user-agent");
Browser browser = UserAgent.parseUserAgentString(userAgent).getBrowser();
log.info("browser Name:"+browser.getName());
if(browser!=null&&browser.getName().contains("Chrome")){
Version version = browser.getVersion(userAgent);
if(version.getMajorVersion()!=null){
try{
int majorVersion = Integer.parseInt(version.getMajorVersion());
log.info("majorVersion:"+majorVersion);
// 如果是谷歌并且版本小于67,则设置为null
if(majorVersion<67){
return null;
}
}catch (Exception e ){
e.printStackTrace();
}
}
}
return "None";
}
添加cookie
String sameSize=CookieUitl.getSameSize(request);
ResponseCookie cookie = ResponseCookie.from(RANDOM_CODE_KEY, sRand.toString()) // key & value
.httpOnly(false) // 禁止js读取
.secure(false) // 在http下也传输
.path("/") // path
.maxAge(Duration.ofHours(1)) // 1个小时候过期
.sameSite(sameSize) // 大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外
.secure(true)
.build();
//若一个请求中要添加多个cookie,改为addHeader
response.setHeader("Set-Cookie",cookie.toString());