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

Spring Security升级后filterChain Bean创建失败:AlreadyBuiltException问题

问题排查与解决:Spring Security升级后AlreadyBuiltException错误

问题原因

错误AlreadyBuiltException: This object has already been built的核心诱因:

  • 在filterChain方法中调用authenticationManager(http.getSharedObject(AuthenticationManagerBuilder.class))时,会触发AuthenticationManagerBuilder的build()方法,该操作会将当前HttpSecurity实例的构建状态标记为已完成。
  • 后续执行http.build()尝试构建SecurityFilterChain时,HttpSecurity已处于已构建状态,因此抛出异常。

解决方案

修改filterChain方法,直接注入Spring容器中已定义的AuthenticationManager Bean,而非通过HttpSecurity的共享对象动态创建。

修改后的完整配置类

package com.github.marceloasfilho.wallet.configuration;

import com.github.marceloasfilho.wallet.filter.JwtAuthenticationFilter;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

import static org.springframework.security.config.Customizer.withDefaults;

@Configuration
@RequiredArgsConstructor
public class SecurityConfiguration {

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();

        manager.createUser(User.withUsername("Marcelo")
                .passwordEncoder(bCryptPasswordEncoder()::encode)
                .password("password")
                .roles("USER")
                .build());

        manager.createUser(User.withUsername("john")
                .passwordEncoder(bCryptPasswordEncoder()::encode)
                .password("1234")
                .roles("USER", "MANAGER")
                .build());

        manager.createUser(User.withUsername("will")
                .passwordEncoder(bCryptPasswordEncoder()::encode)
                .password("1234")
                .roles("ADMIN")
                .build());

        manager.createUser(User.withUsername("jim")
                .passwordEncoder(bCryptPasswordEncoder()::encode)
                .password("1234")
                .roles("ADMIN")
                .build());

        manager.createUser(User.withUsername("arnold")
                .passwordEncoder(bCryptPasswordEncoder()::encode)
                .password("1234")
                .roles("SUPER_ADMIN")
                .build());

        return manager;
    }

    // 修改点:注入AuthenticationManager Bean
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception {
        http.csrf().disable()
                .authorizeHttpRequests()
                .antMatchers(HttpMethod.POST)
                .hasAnyRole("ADMIN", "SUPER_ADMIN")
                .antMatchers(HttpMethod.GET)
                .hasAnyRole("USER", "MANAGER")
                .and()
                .httpBasic(withDefaults())
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        // 使用注入的AuthenticationManager
        http.addFilter(new JwtAuthenticationFilter(authenticationManager));

        return http.build();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth) throws Exception {
        return auth
                .userDetailsService(userDetailsService())
                .passwordEncoder(bCryptPasswordEncoder())
                .and()
                .build();
    }
}

关键修改说明

  1. 在filterChain方法参数中添加AuthenticationManager authenticationManager,让Spring自动注入已定义好的AuthenticationManager Bean。
  2. 将http.addFilter(new JwtAuthenticationFilter(authenticationManager(http.getSharedObject(AuthenticationManagerBuilder.class))))替换为http.addFilter(new JwtAuthenticationFilter(authenticationManager)),直接使用注入的Bean。

此修改避免了在HttpSecurity构建流程中重复触发AuthenticationManager的build操作,彻底解决AlreadyBuiltException问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 07:35:18