Spring Security迁移FilterChain后登录重定向丢失AuthenticationToken问题
问题原因分析
你的配置存在两个核心冲突点,导致认证成功后会话无法正确保留AuthenticationToken:
- 登录过滤器重复配置:同时启用了
formLogin()和自定义的MyAuthenticationFilter,两者都会处理登录请求。formLogin()会自动添加默认的UsernamePasswordAuthenticationFilter,和你自定义的过滤器处于同一执行位置,导致会话存储逻辑混乱。 - AuthenticationManager未注册为Bean:自定义的
formUserAuthManager()没有标注@Bean注解,Spring Security无法将其纳入全局上下文管理,后续请求无法从会话中正确加载认证信息。
修复方案
步骤1:移除冲突的formLogin配置
既然已经自定义了登录过滤器,无需保留默认的formLogin()配置,避免过滤器重复执行:
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.csrf(AbstractHttpConfigurer::disable) .requestCache(c -> c.requestCache(new CustomRequestCache())) .addFilterAt(getFormAuthFilter(), UsernamePasswordAuthenticationFilter.class) .authorizeHttpRequests(a -> a.requestMatchers(SecurityUtils::isFrameworkInternalRequest).permitAll() .anyRequest().authenticated() ) // 移除默认formLogin配置 .headers(h -> h.frameOptions(FrameOptionsConfig::sameOrigin)); return http.build(); }
步骤2:将AuthenticationManager注册为Bean
给formUserAuthManager()添加@Bean注解,让Spring容器管理该实例:
@Bean AuthenticationManager formUserAuthManager() { return authentication -> authProvider().authenticate(authentication); }
步骤3:确保自定义过滤器正确处理会话存储
如果MyAuthenticationFilter继承自AbstractAuthenticationProcessingFilter,需配置会话认证策略,确保认证信息存入会话:
public MyAuthenticationFilter() { super(new AntPathRequestMatcher("/login", "POST")); // 添加默认会话固定保护策略,自动处理会话存储 setSessionAuthenticationStrategy(new SessionFixationProtectionStrategy()); }
同时检查MyLoginSuccessHandler,确保它没有破坏默认的会话保存逻辑,必要时手动绑定认证信息到会话:
public class MyLoginSuccessHandler implements AuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { // 将认证信息存入SecurityContext SecurityContextHolder.getContext().setAuthentication(authentication); // 绑定到HttpSession request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, SecurityContextHolder.getContext()); // 执行重定向逻辑 response.sendRedirect("/dashboard"); } }
步骤4:检查CustomRequestCache实现
确保自定义请求缓存正确操作会话,避免干扰认证信息存储:
public class CustomRequestCache extends HttpSessionRequestCache { @Override public void saveRequest(HttpServletRequest request, HttpServletResponse response) { // 仅保存非框架内部请求 if (!SecurityUtils.isFrameworkInternalRequest(request)) { super.saveRequest(request, response); } } }
验证要点
- 登录成功后,检查HttpSession中是否存在
SPRING_SECURITY_CONTEXT属性,且包含有效的Authentication对象。 - 重定向后的请求,检查
SecurityContextHolder.getContext().getAuthentication()是否不为空且不是匿名认证。
内容的提问来源于stack exchange,提问作者tagtraeumer
相关产品推荐
相关产品推荐

