Spring Security 5.7.3:JWT登录时authenticationManager为null问题求助
问题原因及修复方案
1. 核心问题:AuthenticationManager未注入控制器
你的AuthenticationController中声明了AuthenticationManager和JwtTokenProvider字段,但没有通过Spring依赖注入完成初始化,导致调用authenticationManager.authenticate()时触发空指针异常。
修复步骤
步骤1:修复控制器的依赖注入
给AuthenticationController添加@RequiredArgsConstructor注解,并将字段改为final,让Lombok自动生成构造函数完成依赖注入:
@RestController @RequestMapping("/auth") @RequiredArgsConstructor public class AuthenticationController { private final AuthenticationManager authenticationManager; private final JwtTokenProvider jwtTokenProvider; @PostMapping("/login") public String login(@RequestBody UserRequest userLoginRequest) { UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userLoginRequest.getUserName(), userLoginRequest.getPassword()); Authentication auth = authenticationManager.authenticate(authenticationToken); SecurityContextHolder.getContext().setAuthentication(auth); // 修正:存入已认证的auth对象而非原始token String jwtToken = jwtTokenProvider.generateJwtToken(auth); return "Bearer " + jwtToken; } }
同时确保JwtTokenProvider类上添加了@Component或@Service注解,使其成为Spring管理的Bean。
步骤2:优化SecurityConfig中的AuthenticationManager配置
改用AuthenticationConfiguration获取AuthenticationManager(Spring Boot 2.7+推荐方式),同时单独定义PasswordEncoder Bean保证全局复用:
@Configuration @EnableWebSecurity @RequiredArgsConstructor public class SecurityConfig { private final UserDetailsService jwtUserDetailsService; private final JwtAuthenticationEntryPoint handler; @Bean public JwtAuthenticationFilter jwtAuthenticationFilter() { return new JwtAuthenticationFilter(); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception { return authConfig.getAuthenticationManager(); } @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOrigin("*"); config.addAllowedHeader("*"); config.addAllowedMethod("OPTIONS"); config.addAllowedMethod("HEAD"); config.addAllowedMethod("GET"); config.addAllowedMethod("PUT"); config.addAllowedMethod("POST"); config.addAllowedMethod("DELETE"); config.addAllowedMethod("PATCH"); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } @Bean public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { httpSecurity .cors() .and() .csrf().disable() .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class) .exceptionHandling().authenticationEntryPoint(handler).and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() .authorizeRequests() .antMatchers("/auth/**").permitAll() // 简化匹配规则,覆盖所有/auth端点 .anyRequest().authenticated(); return httpSecurity.build(); } }
额外修正点
- 登录方法中,
SecurityContextHolder.getContext().setAuthentication(auth)应传入认证后的auth对象,而非原始的authenticationToken,确保上下文存储的是已认证的用户信息。
内容的提问来源于stack exchange,提问作者Mustafa
相关产品推荐
相关产品推荐

