Cookie 的SameSite属性用来限制第三方 Cookie,从而减少安全风险。
它可以设置三个值。
Strict
Lax
None
1、Strict 最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie。
Set-Cookie: CookieName=CookieValue; SameSite=Strict;
这个规则过于严格,可能造成非常不好的用户体验。比如,当前网页有一个 GitHub 链接,用户点击跳转就不会带有 GitHub 的 Cookie,跳转过去总是未登陆状态。
2、Lax 规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外。
Set-Cookie: CookieName=CookieValue; SameSite=Lax;
3、None 网站可以选择显式关闭SameSite属性,将其设为None。不过,前提是必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效。
下面的设置无效。
Set-Cookie: widget_session=abc123; SameSite=None
下面的设置有效。
Set-Cookie: widget_session=abc123; SameSite=None; Secure
现在做系统,很多时候会有系统内嵌的情况发生(比如主平台系统需要嵌入第三方系统,第三方需要进行改造),内嵌的系统也需要存储登录信息,但是由于samesite的原因导致cookie不能用,则session也不可用。而且糟糕的是local/session story也不可用。导致web浏览器端无法将登录会话信息保存。那么使得系统不能保持登录状态。
解决方案是将内嵌的系统改成https。将samesite=none;secure 来让cookie有效。可以将会话等等信息存储到cookie中,这样就可以保持登录会话信息了。
低版本的servlet cookie不支持samesite属性,项目也不能升级到高版本。解决方案为:
在项目新建一个 CookieFilter 去实现servlet 的filter。在其中进行httpservletresponse warp。
将response.addCookie() 进行改写成
public void addCookie(Cookie cookie){
//其他cookie属性自行补充
String value = cookie.getName()+"="+cookie.getValue()+";SameSite=None;Secure";
response.setHeader("Set-Cookie",value);
}
这样就可以让此filter之后的addCookie都是带有SameSite属性的,保证了cookie的有效性。
还有一个解决方案就是两个网站使用同一个一级域名,
比如a网站域名为: a.xxxx.com
b网站域名为: b.xxxx.com