SpringBoot3中SecurityFilterChain内AuthenticationManager注入问题求助
Spring Boot 3 中为自定义Jwt过滤器注入AuthenticationManager的解决方案
在Spring Boot 3版本的Security配置中,直接调用authenticationManager()实例化自定义JwtUsernameAndPasswordAuthenticationFilter会触发错误,这是因为Spring Security 6(Spring Boot 3默认集成)的配置方式发生了变化,原有的AuthenticationManagerBuilder配置逻辑和直接调用authenticationManager()的方式不再适用。以下是适配方案:
修改步骤
- 将AuthenticationManager暴露为Spring Bean
移除原有的configure(AuthenticationManagerBuilder)方法,通过@Bean方法基于AuthenticationConfiguration构建并暴露AuthenticationManager,确保Spring容器可以管理该实例。 - 在SecurityFilterChain中注入AuthenticationManager
不再直接调用authenticationManager(),而是通过方法参数注入已暴露的AuthenticationManager实例,用于初始化自定义过滤器。 - 更新Security配置语法
Spring Security 6中authorizeRequests()已被authorizeHttpRequests()替代,同时推荐使用Lambda风格的配置写法替代原链式调用。
修改后的完整代码
ApplicationSecurityConfig配置类
@Configuration @EnableWebSecurity @EnableMethodSecurity public class ApplicationSecurityConfig { private final PasswordEncoder passwordEncoder; private final ApplicationUserService applicationUserService; public ApplicationSecurityConfig(PasswordEncoder passwordEncoder, ApplicationUserService applicationUserService) { this.passwordEncoder = passwordEncoder; this.applicationUserService = applicationUserService; } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception { return http .csrf(csrf -> csrf.disable()) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .addFilter(new JwtUsernameAndPasswordAuthenticationFilter(authenticationManager)) .authorizeHttpRequests(auth -> auth .requestMatchers("/", "/index", "/css/*", "/js/*").permitAll() .requestMatchers("/api/**").hasRole(ApplicationUserRole.STUDENT.name()) .anyRequest().authenticated()) .build(); } @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception { return authConfig.getAuthenticationManager(); } @Bean public DaoAuthenticationProvider daoAuthenticationProvider() { DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setPasswordEncoder(passwordEncoder); provider.setUserDetailsService(applicationUserService); return provider; } }
JwtUsernameAndPasswordAuthenticationFilter过滤器类
(过滤器核心逻辑无需修改,保持原有实现即可)
public class JwtUsernameAndPasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter { private final AuthenticationManager authenticationManager; public JwtUsernameAndPasswordAuthenticationFilter(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { try { UsernameAndPasswordAuthenticationRequest authenticationRequest = new ObjectMapper() .readValue(request.getInputStream(), UsernameAndPasswordAuthenticationRequest.class); Authentication authentication = new UsernamePasswordAuthenticationToken( authenticationRequest.getUsername(), authenticationRequest.getPassword() ); return authenticationManager.authenticate(authentication); } catch (IOException e) { throw new RuntimeException(e); } } @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { String key = "securesecuresecuresecuresecuresecuresecuresecuresecuresecure"; String token = Jwts.builder() .setSubject(authResult.getName()) .claim("authorities", authResult.getAuthorities()) .setIssuedAt(new Date()) .setExpiration(java.sql.Date.valueOf(LocalDate.now().plusWeeks(2))) .signWith(Keys.hmacShaKeyFor(key.getBytes())) .compact(); response.addHeader("Authorization", "bearer " + token); } }
关键说明
- 通过
AuthenticationConfiguration获取AuthenticationManager是Spring Security 6的推荐方式,它会自动应用你配置的DaoAuthenticationProvider。 - Lambda风格的配置写法让代码更简洁,同时适配了Spring Security 6的API变更。
内容的提问来源于stack exchange,提问作者Ace Thoughtless
相关产品推荐
相关产品推荐

