如何解决这个bean冲突?

问题描述 投票:0回答:1

我正在尝试将登录和注册添加到我的 API 应用程序中。但我遇到了问题。两个bean 相互冲突。我将与这些 bean 交互的所有类都放在消息中。

2024-03-11T00:13:22.768+03:00  WARN 22820 --- [           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityController': Unsatisfied dependency expressed through method 'setAuthenticationManager' parameter 0: Error creating bean with name 'authenticationManager' defined in class path resource [com/weather/weather/config/SecurityConfigurator.class]: Failed to instantiate [org.springframework.security.authentication.AuthenticationManager]: Factory method 'authenticationManager' threw exception with message: No qualifying bean of type 'org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder' available: expected single matching bean but found 2: authenticationManagerBuilder,configureAuthenticationManagerBuilder
2024-03-11T00:13:22.769+03:00  INFO 22820 --- [           main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2024-03-11T00:13:22.771+03:00  INFO 22820 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2024-03-11T00:13:22.774+03:00  INFO 22820 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
2024-03-11T00:13:22.776+03:00  INFO 22820 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
2024-03-11T00:13:22.788+03:00  INFO 22820 --- [           main] .s.b.a.l.ConditionEvaluationReportLogger : 

Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2024-03-11T00:13:22.800+03:00 ERROR 22820 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of method setAuthenticationManager in com.weather.weather.controller.SecurityController required a single bean, but 2 were found:
    - authenticationManagerBuilder: defined by method 'authenticationManagerBuilder' in class path resource [org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.class]
    - configureAuthenticationManagerBuilder: defined by method 'configureAuthenticationManagerBuilder' in class path resource [com/weather/weather/config/SecurityConfigurator.class]

This may be due to missing parameter name information

Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

Ensure that your compiler is configured to use the '-parameters' flag.
You may need to update both your build tool settings as well as your IDE.

安全配置器

@Configuration
@EnableWebSecurity
@Data
public class SecurityConfigurator {
    private UserService userService;
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration)throws Exception{
        return authenticationConfiguration.getAuthenticationManager();
    }

    @Bean
    public AuthenticationManagerBuilder configureAuthenticationManagerBuilder(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder.userDetailsService(userService).passwordEncoder(passwordEncoder());
        return authenticationManagerBuilder;
    }
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .cors(AbstractHttpConfigurer::disable)
                .cors(httpSecurityCorsConfigurer ->
                        httpSecurityCorsConfigurer.configurationSource(request ->
                                new CorsConfiguration().applyPermitDefaultValues())
                )
                .exceptionHandling(exceptions -> exceptions.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)))
                .sessionManagement(session -> session
                        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                )
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers("/auth/**").permitAll()
                        .requestMatchers("/api/v1/weather").fullyAuthenticated()
                        .anyRequest().permitAll()
                );
        return http.build();
    }
}

安全控制器

@RestController
@RequestMapping("/auth")
public class SecurityController {
    private UserRepository userRepository;
    private PasswordEncoder passwordEncoder;
    private AuthenticationManager authenticationManager;
    private JwtCore jwtCore;

    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    @Autowired
    public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
        this.passwordEncoder = passwordEncoder;
    }
    @Autowired
    public void setAuthenticationManager(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }
    @Autowired
    public void setJwtCore(JwtCore jwtCore) {
        this.jwtCore = jwtCore;
    }


    @PostMapping("/signup")
    ResponseEntity<?> signup(@RequestBody SignUpRequest signUpRequest){
        if(userRepository.existsUserByUsername(signUpRequest.getUsername())){
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("This nickname already exist");
        }
        User user = new User();
        user.setUsername(signUpRequest.getUsername());
        user.setPassword(passwordEncoder.encode(signUpRequest.getPassword()));
        userRepository.save(user);
        return ResponseEntity.ok("Chinazes");

    }

    @PostMapping("/signin")
    ResponseEntity<?> signin(@RequestBody SignInRequest signInRequest){
        Authentication authentication = null;
        try{
            authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(signInRequest.getUsername(),signInRequest.getPassword()));
        } catch (BadCredentialsException e){
            return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
        }
        SecurityContextHolder.getContext().setAuthentication(authentication);
        String jwt = jwtCore.generateToken(authentication);
        return ResponseEntity.ok(jwt);

    }

}

我尝试使用

@Primary
@Qualifier
,但它们导致了更多错误。我不明白为什么 Spring 会抱怨它,如果这些 bean 是不同的。

java spring-boot javabeans
1个回答
0
投票

问题在于

@EnableWebSecurity
创建了一个
AuthenticationManagerBuilder
bean,而您也这样做了。我在本地确认,如果您用
@Primary
标记 AuthenticationManagerBuilder,错误就会消失,因为 Spring Boot 现在能够确定在您的
SecurityController
中使用哪个 bean。

© www.soinside.com 2019 - 2024. All rights reserved.