Spring Security本地正常但服务器getAuthentication()返回null是什么原因
问题根因
对比本地和服务器日志可以发现,核心差异是服务器跳转/foo时,HttpSessionSecurityContextRepository 没有读取到之前存入Session的SecurityContext,直接返回了空上下文,后续被判定为匿名用户导致鉴权失败。
排查与解决方法
1. 优先检查会话序列化问题
SecurityContext存入HttpSession时需要序列化所有关联对象,你当前的LoginInfoEntity没有实现Serializable接口会导致序列化失败,虽然存储日志打印正常,但实际Session中存储的对象异常,后续读取时反序列化失败直接返回空上下文,这是本地正常、服务器异常的高频诱因。
解决方法:给LoginInfoEntity类添加序列化实现:public class LoginInfoEntity implements Serializable { private static final long serialVersionUID = 1L; // 原有代码保持不变 }2. 检查Cookie配置和反向代理设置
如果服务器前端部署了Nginx等反向代理,很可能因为代理头转发不全,导致Spring生成的Session Cookie域名、路径、安全属性和实际访问场景不匹配,浏览器后续请求不会携带Session Cookie,自然找不到对应会话。
解决方法:- 反向代理配置添加头转发(以Nginx为例):
proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;- Spring Boot配置文件添加参数开启转发头识别:
server.forward-headers-strategy=native- 必要时手动指定Session Cookie配置,在SecurityConfig的
configure(HttpSecurity http)方法中添加:
http.sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) .cookieConfig() .path("/") .httpOnly(true) .secure(false); // 若服务器使用HTTPS请改为true3. 调整认证成功处理器
你自定义的AuthenticationSuccessHandler没有继承Spring默认的成功处理器逻辑,极端场景下会出现会话同步异常。可以替换为Spring提供的默认成功跳转逻辑简化配置:// 替换原有successHandler配置 .formLogin() .loginPage(loginPage) .loginProcessingUrl(loginSuccessUrl) .defaultSuccessUrl(fooPage, true) // 会话超时可以全局配置,在application.properties中添加: // server.servlet.session.timeout=180000
内容的提问来源于stack exchange,提问作者bittap
相关产品推荐
相关产品推荐

