后端跨域cookie问题与spring-session-data-redis
背景
1、后端统一接入了公司内部登录系统,登录后cookie信息在域名:test.net.cn下。
Set-Cookie:SESSION=09a2f617-66a0-4e02-b99f-130d83900321; Domain=test.net.cn; Path=/; HttpOnly; SameSite=Lax
2、当我们的系统接入到统一登录系统后,若访问域名为a.test.net.cn,则不会出现问题,因为在他的子域名下,cookie是共享的,当跳转到我们系统后
sessionid是不会重新生成的,没问题
3、当我们的系统接入到统一登录系统后,若访问域名为a.test.net.cn:2531,则就会出现问题,因为域名不同,请求到后端,框架会认为本次请求不是同一个会话,
所以会在a.test.net.cn下再次写入一个cookie携带sessionId(说明:cookie的写入,domain是自动过滤端口的)
解释:
后端什么时候会判断写入cookie了,requset.getSeesion().getAttribute("");这个方法就会写入,查看源码可知,request.getSession();这个方法,默认为:
若本次请求的host下没有sessionId,则判断为新的会话,会重新创建一个sessionId,并写入到响应头里去:
解决方案:
1、添加cookie写入值配置
import org.springframework.session.web.http.DefaultCookieSerializer; public class NonWriteCookieSerializer extends DefaultCookieSerializer { @Override public void writeCookieValue(CookieValue cookieValue) { } }
2、配置后端cookie配置
pattern: ^.+?\.(\w+\.\w+\.[a-z]+)$
@Bean public DefaultCookieSerializer defaultCookieSerializer() { DefaultCookieSerializer cookieSerializer = new NonWriteCookieSerializer(); cookieSerializer.setDomainNamePattern(pattern); cookieSerializer.setUseBase64Encoding(false); return cookieSerializer; }
注意:\的问题,直接写入到字符串里面为:
cookieSerializer.setDomainNamePattern("^.+?\\.(\\w+\\.\\w+\\.[a-z]+)$");
该正则表达式为任意域名,也就是和当前的cookie会话域名保持一致
3、设置request.getSession()方法,防止重复写入session
request.getSession(false).getAttribute(Constants.SESSION_ATTRIBUTE_USER);
这样可以防止重新创建sessionId,以及就算框架写入cookie其实值也是写不进去的,保证每次会话请求的sessionId与test.net.cn保持一致。
大功告成:这样就算登录的域名和子系统的域名不在同一个域名下,也可以通过spring-session-data-redis保持登录的统一性
建议:作为正式系统,还是建议各个子系统和登录系统在同一个域名下,这样才是最合规的