#背景
使用spring cloud gateway开发的网关服务,业务部门需要接入摄像头使用,就是在登录时,支持摄像头登录。由于之前都是通过配置成http协议访问网关,然后由网关服务进行后台转发,但是现在集成的摄像头接口,只支持https协议进行调用,因此业务部门开发人员使用了两套网关服务,一套配置成https协议,只转发摄像头请求,一套配置成http协议,转发其他请求;两套直接使用同一个sso进行单点登录验证;两个网关部署在同一台服务器上,分别使用443和80端口。
在这种情况下,无论先登录http服务还是https服务,同一个浏览器访问另一个服务时,都能实现sso自动跳转进行免密登录。但是注销时,情况却不一样,当在https服务中进行注销后,刷新http服务页面,会自动跳转到登录认证页面;当首先在http服务中进行注销后,刷新https服务页面,却仍能正常访问,不会跳转到登录认证页面。
解决方案
首先构造测试环境,复现问题
在本地开发机使用idea启动了两个网关服务,分别为https和http协议,可以转发到相同的sso。默认情况下,现象确实如此。
分析跟踪问题
分析注销场景,当注销时,网关服务在后台清理session信息,主要是redis中保存的session相关信息;然后返回的response的header中,使用set-cookie通知浏览器清理会话信息。实际运行场景下,当登录成功时,通过浏览器调试窗口可以看到,http服务中的cookie中没有session信息,只有CASTGC信息,而https服务的cookie中包括了session、CASTGC信息;但是单独登录http服务,会出现session信息,因此可以推断https服务进行单点登录时会清除掉http的session信息。当http服务退出登录时,其相应头包含Set-COokie: session=;Max-Age=0;expires=Thu,01-Jan-1970 00:00:00 GMT;Path=/;HttpOnly
的内容进行清除,但是由于session信息在http和https服务是共用的,当使用了https服务时,session信息多了个secure的属性,该属性会导致http服务的set-cookie相应无法正确起作用,F12查看,会看到一个黄色三角号进行警告:This Set-Cookie was blocked because it had the "Secure" attribute but was not received over a secure connection. This Set-Cookie was blocked because it was not sent over a secure-connection and would have overwritten a cookie with Secure attribute.
通过以上分析,总结如下: 当一个服务,采用了相同的域名或ip对外同时提供http服务和https服务时,浏览器中session是共享的(在cookie当中可以看到domain属性只区分到域名或ip,不会包括端口信息)。当使用https服务时,cookie中的session属性中包括了secure属性,该属性会导致session属性无法通过http请求进行修改,从而表现出,http服务注销后,https服务仍在登录状态。
解决办法
根据以上分析,在https服务中,登录设置session时,去掉secure属性即可。具体解决代码如下:
1 |
|
通过自定义WebSessionIdResolver
,覆盖掉spring cloud gateway中默认的WebSessionIdResolver
,可以在每次响应设置session时,进行自定义secure属性设置;secureState
开关可以设置是否打开该功能。
关闭secure属性,会降低https的服务的安全性,如无必要,不建议设置。