自定义Filter认证后仍获取到anonymousUser问题求助
问题排查与解决步骤
1. 确认自定义过滤器的位置
确保你的JSON登录过滤器替换了原UsernamePasswordAuthenticationFilter的位置,且在SessionManagementFilter之前执行——SessionManagementFilter负责从会话加载SecurityContext,你的过滤器需要先完成认证并保存上下文,后续流程才能正确读取。
组件式配置(替代WebSecurityConfigurerAdapter)中注册过滤器时指定顺序:
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .addFilterAt(customJsonLoginFilter(), UsernamePasswordAuthenticationFilter.class) .sessionManagement(session -> session .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) // 默认配置,确保会话正常创建 ); // 其他权限、路径配置... return http.build(); }
2. 保证认证成功后正确持久化SecurityContext
自定义过滤器在认证通过后,除了设置SecurityContextHolder,必须通过AuthenticationSuccessHandler完成会话持久化:
方式1:复用默认SuccessHandler逻辑
public class CustomJsonLoginFilter extends UsernamePasswordAuthenticationFilter { // 构造方法、认证逻辑实现... @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { SecurityContextHolder.getContext().setAuthentication(authResult); // 调用默认SuccessHandler,它会自动将上下文存入会话 getSuccessHandler().onAuthenticationSuccess(request, response, authResult); } }
方式2:自定义SuccessHandler时手动持久化
public class CustomSuccessHandler implements AuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { SecurityContext context = SecurityContextHolder.createEmptyContext(); context.setAuthentication(authentication); SecurityContextHolder.setContext(context); // 将上下文存入会话,这一步是关键 request.getSession().setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, context); // 执行重定向或其他逻辑 response.sendRedirect("/"); } }
3. 检查SecurityContextRepository配置
Spring Security默认用HttpSessionSecurityContextRepository管理会话中的上下文,确保未被错误覆盖:
@Bean public SecurityContextRepository securityContextRepository() { return new HttpSessionSecurityContextRepository(); } // 在SecurityFilterChain中绑定 http.securityContext(context -> context .securityContextRepository(securityContextRepository()) );
4. 排查会话一致性问题
认证成功后打印会话ID,验证重定向后的请求是否携带同一个会话:
// 认证成功时打印 System.out.println("认证会话ID:" + request.getSession().getId()); // 首页请求时打印 System.out.println("首页会话ID:" + request.getSession().getId()); System.out.println("当前认证用户:" + SecurityContextHolder.getContext().getAuthentication());
如果会话ID不一致,说明重定向时Cookie丢失,检查浏览器Cookie设置或响应头的Cookie配置。
5. 临时排除CSRF干扰(仅测试阶段)
如果是POST登录请求,可临时禁用CSRF确认是否是CSRF导致的会话异常:
http.csrf(csrf -> csrf.disable());
内容的提问来源于stack exchange,提问作者Yousef Ali
相关产品推荐
相关产品推荐

