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

Spring Boot 3添加JWT过滤器至过滤链报‘已构建’错误求解

Spring Boot 3 解决SecurityFilterChain与AuthenticationManager构建冲突问题

问题描述

配置Spring Security时,添加JWT过滤器后触发异常:

Factory method 'filterChain' threw exception with message: This object has already been built

移除JWT过滤器后系统正常运行,原因是AuthenticationManager构建时已触发HttpSecurity对象的build操作,后续filterChain方法再次调用http.build()就会触发冲突。

原有配置代码

SecurityFilterChain 配置方法

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .csrf().disable()
        .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
        .addFilter(new JwtUserNameAndPasswordAuthFilter(authManager(http)))
        .authorizeHttpRequests()
            .requestMatchers("/", "/index.html", "/css/*", "/js/*").permitAll()
            .requestMatchers("/api/**").hasRole(STUDENT.name())
            .anyRequest().authenticated();

    return http.build();
}

AuthenticationManager 配置方法

@Bean
public AuthenticationManager authManager(HttpSecurity http) throws Exception {
    AuthenticationManagerBuilder authenticationManagerBuilder = http
                                .getSharedObject(AuthenticationManagerBuilder.class);
    authenticationManagerBuilder.authenticationProvider(daoAuthenticationProvider());
    return authenticationManagerBuilder.build();
}

解决方案

方案一:直接在HttpSecurity链中配置AuthenticationProvider

去掉单独的authManager Bean,直接将AuthenticationProvider配置到HttpSecurity的链式调用中,让Spring Security自动处理AuthenticationManager的创建,避免提前触发HttpSecurity的build操作:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .csrf().disable()
        .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
        .authenticationProvider(daoAuthenticationProvider()) // 直接注入自定义Provider
        .addFilter(new JwtUserNameAndPasswordAuthFilter(http.getSharedObject(AuthenticationManager.class)))
        .authorizeHttpRequests()
            .requestMatchers("/", "/index.html", "/css/*", "/js/*").permitAll()
            .requestMatchers("/api/**").hasRole(STUDENT.name())
            .anyRequest().authenticated();

    return http.build();
}

// 保留自定义AuthenticationProvider的Bean配置
@Bean
public DaoAuthenticationProvider daoAuthenticationProvider() {
    DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
    // 配置UserDetailsService和PasswordEncoder等
    provider.setUserDetailsService(userDetailsService());
    provider.setPasswordEncoder(passwordEncoder());
    return provider;
}

方案二:通过AuthenticationConfiguration获取AuthenticationManager

如果需要保留独立的AuthenticationManager Bean供其他地方使用,不要从HttpSecurity中手动构建,而是通过AuthenticationConfiguration获取:

@Bean
public AuthenticationManager authManager(AuthenticationConfiguration authConfig) throws Exception {
    return authConfig.getAuthenticationManager();
}

@Bean
public SecurityFilterChain filterChain(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception {
    http
        .csrf().disable()
        .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
        .addFilter(new JwtUserNameAndPasswordAuthFilter(authenticationManager)) // 注入已构建好的AuthenticationManager
        .authorizeHttpRequests()
            .requestMatchers("/", "/index.html", "/css/*", "/js/*").permitAll()
            .requestMatchers("/api/**").hasRole(STUDENT.name())
            .anyRequest().authenticated();

    return http.build();
}

@Bean
public DaoAuthenticationProvider daoAuthenticationProvider() {
    DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
    provider.setUserDetailsService(userDetailsService());
    provider.setPasswordEncoder(passwordEncoder());
    return provider;
}

原理说明

  • 方案一利用Spring Security的链式配置特性,将AuthenticationProvider直接绑定到HttpSecurity,在最终调用http.build()时才统一构建AuthenticationManager和SecurityFilterChain,避免了重复构建的冲突。
  • 方案二通过AuthenticationConfiguration获取全局的AuthenticationManager,由Spring统一管理其生命周期,不会和HttpSecurity的构建流程产生交叉冲突。

内容的提问来源于stack exchange,提问作者derstauner

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 19:23:11