Spring/Spring Security

[Spring Secururity ERROR] 스프링 빈 순환 참조 에러 The dependencies of some of the beans i

빅콜팝 2022. 10. 30. 19:20
728x90
반응형

스프링 시큐리티 설정 파일 세팅 중 비밀번호 암호화 설정을 위해 PasswordEncoder 반환 타입의 메소드를 선언 하는 중 순환 참조 오류가 발생하였다.


Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.

순환 참조에 의존하는 것은 권장되지 않으며 기본적으로 금지되어 있습니다. Bean 간의 종속성 주기를 제거하도록 애플리케이션을 업데이트하십시오. 최후의 수단으로 spring.main.allow-circular-references를 true로 설정하여 자동으로 주기를 끊을 수 있습니다.

nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'passwordEncoder': Requested bean is currently in creation: Is there an unresolvable circular reference?

bean 생성 오류: 요청된 bean이 현재 생성 중입니다: 확인할 수 없는 순환 참조가 있습니까?

@Configuration
@RequiredArgsConstructor
public class SecurityConfig {

    private final UserDetailsService userDetailsService;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

       ...

        http.rememberMe() // 사용자 저장
                .rememberMeParameter("idMaintain") // default 파라미터는 remember-me
                .tokenValiditySeconds(604800) // 7일로 설정(default 14일)
                .alwaysRemember(false)
                .userDetailsService(userDetailsService)
        ;

       ...
       
        return http.build();

    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

}

 

PasswordEncoder 반환 타입의 빈 생성 중 순환 참조가 발생하였다.
원인을 살펴보니 remember-me(자동 로그인) 에서 로그인 사용자의 정보를 저장하기 위해 사용되던 UserDetailsService 인터페이스를 의존성 주입하는 과정에서 passwordEncoder를 선언해 주는 부분이 있어 이 부분이 순환 참조가 발생한 것으로 보였다.

public class User implements UserDetails, CredentialsContainer {

	...

    @Deprecated
    public static UserBuilder withDefaultPasswordEncoder() {
       logger.warn("User.withDefaultPasswordEncoder() is considered unsafe for production "
             + "and is only intended for sample applications.");
       PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
       return builder().passwordEncoder(encoder::encode);
    }
    
    ...
    
}


몇시간 동안의 삽질 끝에 passwordEncoder 메서드를 정적(static)으로 선언하는 방식으로 해결..
정적 메서드는 표준 인스턴스화된 개체에서 벗아나 정적 메서드를 직접 호출하기 때문에 인스턴스화를 하지 않아 순환참조에서 벗어날 수 있었다.

@Bean
public static PasswordEncoder passwordEncoder() {
    return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}


알고보면 아주 간단한데 두시간을 날렸다 ㅜ


Reference

 

Spring Security circular bean dependency

I'm currently working on a Vaadin spring application. According to the app specifications, authentication/authorization of the users must be completed by querying database via jdbcTemplate. How to ...

stackoverflow.com

 

728x90
반응형