Spring Boot3+Spring Security6认证成功后仍返回匿名用户问题
问题描述
使用Spring Boot 3.0.6 + Spring Security 6.x开发,JwtAuthenticationFilter中已通过UsernamePasswordAuthenticationToken将认证信息存入SecurityContextHolder,日志也验证了认证信息已成功设置,但用Postman访问/api/auth/r/testing接口时,返回结果为anonymousUser。
代码问题分析
核心问题在于没有将JWT过滤器纳入Spring Security的过滤器链管理,而是通过FilterRegistrationBean注册成了Servlet容器级别的过滤器,导致Spring Security无法正确识别并维护你设置的认证上下文:
WebSecurityConfig中注入了JwtAuthenticationFilter实例,但未将其添加到SecurityFilterChain中,Spring Security的过滤器链无法感知到你设置的认证信息。- 虽然用
FilterRegistrationBean设置了最高优先级,但Spring Security的SecurityContextPersistenceFilter会在请求流程中管理上下文,Servlet级过滤器设置的上下文可能被后续Spring Security的过滤器操作覆盖或重置。
解决方案
步骤1:删除FilterConfig类
无需通过FilterRegistrationBean注册JWT过滤器,交由Spring Security的过滤器链管理即可。
步骤2:修改WebSecurityConfig,将JWT过滤器加入Spring Security过滤器链
在filterChain方法中,添加addFilterBefore将JWT过滤器放到UsernamePasswordAuthenticationFilter之前执行:
@Configuration @EnableWebSecurity public class WebSecurityConfig{ @Resource private JwtAuthenticationFilter jwtAuthenticationFilter; @Resource(name = "jwtService") private UserDetailsService userDetailsService; @Bean public PasswordEncoder encoder(){ return new BCryptPasswordEncoder(); } @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception { return config.getAuthenticationManager(); } @Bean public AuthenticationProvider authenticationProvider(){ DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider(); authenticationProvider.setUserDetailsService(userDetailsService); authenticationProvider.setPasswordEncoder(encoder()); return authenticationProvider; } @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{ http.cors().and() .csrf().disable() .authorizeHttpRequests() .requestMatchers("/api/auth/n/**").permitAll() .requestMatchers("/api/auth/r/**").permitAll() .anyRequest().authenticated() // 可根据实际需求调整其他请求的认证规则 .and() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authenticationProvider(authenticationProvider()) // 将JWT过滤器加入Spring Security过滤器链,放在用户名密码认证过滤器之前 .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); return http.build(); } }
步骤3:确保JwtAuthenticationFilter是Spring管理的Bean
在JwtAuthenticationFilter类上添加@Component注解,让Spring自动管理该Bean,避免多实例问题:
@Component public class JwtAuthenticationFilter extends OncePerRequestFilter { // 原有代码保持不变 }
额外检查点
- 确认
jwtTokenUtil.validateToken(jwt)未抛出异常(若验证失败,设置认证信息的代码不会执行)。 - 确认请求头中的
Authorization格式为Bearer {token},无拼写错误。
内容的提问来源于stack exchange,提问作者Monach
相关产品推荐
相关产品推荐

