You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 00:55:34