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

SpringBoot3中SecurityFilterChain内AuthenticationManager注入问题求助

Spring Boot 3 中为自定义Jwt过滤器注入AuthenticationManager的解决方案

在Spring Boot 3版本的Security配置中,直接调用authenticationManager()实例化自定义JwtUsernameAndPasswordAuthenticationFilter会触发错误,这是因为Spring Security 6(Spring Boot 3默认集成)的配置方式发生了变化,原有的AuthenticationManagerBuilder配置逻辑和直接调用authenticationManager()的方式不再适用。以下是适配方案:

修改步骤

  1. 将AuthenticationManager暴露为Spring Bean
    移除原有的configure(AuthenticationManagerBuilder)方法,通过@Bean方法基于AuthenticationConfiguration构建并暴露AuthenticationManager,确保Spring容器可以管理该实例。
  2. 在SecurityFilterChain中注入AuthenticationManager
    不再直接调用authenticationManager(),而是通过方法参数注入已暴露的AuthenticationManager实例,用于初始化自定义过滤器。
  3. 更新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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 06:10:16