新版chrome跨域问题:cookie之SameSite属性

最近在使用前后端分离开发的时候,遇到了一个诡异的问题,无论如何设置跨域,同一个页面获取到的session始终不一致。

事情的起始大概是这样的:

首先说一下我的业务逻辑,其实就是最常见的登录功能,获取验证码后存入session,用户提交登录时,将用户提交的验证码与从session里获取的验证码进行对比;功能简单,也好理解。可是却遇到了如下一系列问题:

发现问题:

  1. 登录界面前后端分离,ajax提交登录时出错。
  2. 验证码接口和登录接口的session不一致(跨域问题);
  3. 在网上搜索跨域问题,重新设置,问题依旧。

错因排除:

  1. ajax允许cookie(已经设置 xhrFields: { withCredentials: true} )。
  2. springboot尝试设置了多种跨域方法(springboot解决跨域)。

深入分析:

  1. 使用其它浏览器(firefox, ie),session却是一致的。。
  2. 对比chrome和firefox请求头和响应头:

firefox:首次发起请求后,服务端返回sessionId后,之后每次请求中的cookie都会带上sessionId。

chrome:请求头始终未携带sessionId,甚至整个cookie都为空,导致服务器每次都接受不到sessionId,每次都会重新分       配 一 个 session。


出现转机:
       搜索chrome未携带cookie原因,发现cookie新属性:SameSite(chrome77版本后支持) 。对该属性的介绍可以参考这篇文章:SameSite。同时,查看chrome的cookie,由于没有指明SameSite的取值,chrome默认将其设置为了Lax:

 

寻找解决方案:

  • DefaultCookieSerializer

   通过CookieSerializer ,我们可以手动的修改SameSite的值。

   @Bean
    public CookieSerializer httpSessionIdResolver() {
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        cookieSerializer.setSameSite(null);
        return cookieSerializer;
    }

 注意,你的项目如果未做session分布式管理,可能需要引入以下依赖才能使用上述类。至于不同Chrome版本号的问题可以参考这篇文章:关于解决Chrome新版本中cookie跨域携带和samesite的问题处理

     <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-core</artifactId>
            <version>2.1.4.RELEASE</version>
        </dependency>

 

  • 设置CookieProcessor(待解决)

全局搜索SameSite,发现tomcat下的CookieProcessor提供了setSameSiteCookies方法,可是设置后无效,,可能是使用方法不对。

  • 设置response的header(推荐)

通过在后端中设置response.setHeader("Set-Cookie", "HttpOnly;Secure;SameSite=None"),响应头可以看到设置的Set-Cookie,但是chrome提示 如下:

由于设置SameSite为NONE时,需要同时设置secure,不设置secure无效,而设置secure之后,必须使用https来传输cookie。相对来说较为安全。
 

  • 我的最终方案:

继续查找资料的时候,幸运的找到了github上对于该问题的探究:New cross-site cookie not 'SameSite' warning in Chrome

看到其中的一条解决方案:  禁用chrome samesite。方法如下:

1. 在chrome中打开链接: chrome://flags/#site-isolation-trial-opt-out,搜索samesite

2.将上述三个选项禁用(设为disable)后重启chrome,问题解决。

 

总结:

      存在即合理,SameSite的设计初衷是为了防止CSRF攻击,禁用SameSite实际上并没有解决问题,属于下下策。这里提供一下我的理解,SameSite为了防止CSRF攻击,加强了对cookie的管理,防止用户带着cookie去访问第三方网站,而这又涉及到了跨域问题。然而,我们不可能要求用户像我们一样去禁用新版chrome的SameSite,目前的建议就是在header中设置samesite,即上述的response.setHeader("Set-Cookie", "HttpOnly;Secure;SameSite=None")后,使用https传输cookie。

时间问题文章逻辑可能并不严谨,仅供参考,如发现错误欢迎指正。

  • 11
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值