인프런 커뮤니티 질문&답변

신석균님의 프로필 이미지
신석균

작성한 질문수

스프링 시큐리티 OAuth2

Ajax 인증시 AuthenticationManager 등록 문의

해결된 질문

작성

·

3.2K

·

수정됨

1

Spring Authorization 1.0 을 사용하여 FormLogin 이 아닌 Ajax로 로그인을 하려고 합니다.

Spring Security 강의를 참조하여

AbstractAuthenticationProcessingFilter를 상속하여 CustomUserDetailsService, CustomAuthenticationProvider, CustomAuthenticationProcessingFilter, CustomAuthenticationToken 구현체를 만들었습니다.

CustomAuthenticationProcessingFilter는 AbstractAuthenticationProcessingFilter 상속하여 개발하였는데 Filter를 등록 하려면 강의에서 내용처럼 AuthenticationManager를 등록 해줘여 하는데 강의는 WebSecurityConfigurerAdapter 상속하여 설정 하는것으로 설명되어 있는데 Spring Securitty 6.0 에서는 삭제되었습니다.

Spring Security 의 강의를 보면

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(ajaxAuthenticationProvider());
    }

configure(AuthenticationManagerBuilder auth)를 구현하고

   @Bean
    public AjaxLoginProcessingFilter ajaxLoginProcessingFilter() throws Exception {
        AjaxLoginProcessingFilter filter = new AjaxLoginProcessingFilter();
        filter.setAuthenticationManager(authenticationManagerBean());
        return filter;
    }

 

질문)AjaxLoginProcessingFilter Bean 에서 설정하는데 SecurityFilterChain 를 등록하는 방식에서는 어떻게 등록해야 할지 문의 합니다.

제가 구현한 소스 일부

  • Authorization Server 설정을 다른 클래스에서 설정하였고 디버깅을 해보니 Authorization Server 용 FilterChain 과 로그인 처리용 FilterChain 이 따로 등록되어 로그인 프로세스는 Spring Security FilterChain Class 에서 진행하였습니다

  • @Configuration는 Spring Security 6에서는 @EnableWebSecurity에 포함되지 않아 추가 하였습니다.

@EnableWebSecurity
@RequiredArgsConstructor
@Configuration
public class DefaultSecurityConfig {
    private final PasswordEncoder passwordEncoder;
    private final CustomAuthenticationProvider customAuthenticationProvider;
//
    @Bean
    public CustomAuthenticationProcessingFilter customAuthenticationProcessingFilter() throws Exception {
        CustomAuthenticationProcessingFilter filter = new CustomAuthenticationProcessingFilter();
        return filter;
    }

    // @formatter:off
    @Bean
    SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(authorizeRequests ->authorizeRequests
                .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
                .requestMatchers("/login/**").permitAll()
                .requestMatchers("/api/registered-client/**").permitAll()
                .anyRequest().authenticated()
            )
            .csrf(csrf -> csrf
                .ignoringRequestMatchers(new AntPathRequestMatcher("/api/registered-client/**"))
            )
            .formLogin().disable();

        http.authenticationProvider(customAuthenticationProvider);
        http.addFilterBefore(customAuthenticationProcessingFilter(), UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }
    // @formatter:on
}

AuthenticationManager를 등록하지 않아 예와가 발생함

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'customAuthenticationProcessingFilter' defined in class path resource [com/naon/oidc/security/config/DefaultSecurityConfig.class]: authenticationManager must be specified

그리고 @Bean으로 만들어 등록하면 순환참조가 됩니다. 

 

답변 1

1

정수원님의 프로필 이미지
정수원
지식공유자

AbstractAuthenticationProcessingFilter 는 객체 생성시 AuthenticationManager 를 필수로 요구 합니다.

AuthenticationManager 는 스프링 시큐리티가 초기화 되면서 생성하고 있는데 AuthenticationManager 를 바로 참조할 수 있는 API 가 제공되지 않습니다.

대신에 초기화 때 AuthenticationManager 를 생성한 설정 클래스를 참조할 수 있습니다.
AuthenticationConfiguration 가 초기화 때 AuthenticationManager 를 생성한 설정 클래스인데 이 클래스로부터 AuthenticationManager 를 얻을 수 있습니다.

일단 아래와 같이 AuthenticationManager 를 사용해 보십시오

@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
    return authenticationConfiguration.getAuthenticationManager();
}
신석균님의 프로필 이미지
신석균
질문자

답변 감사 합니다.

CustomAuthenticationProcessingFilter 에서 AuthenticationManager 등록시 답변주신 방안으로 하면 filter.setAuthenticationManager(authenticationManager(null)); 와 같이 AuthenticationConfiguration을 null 로 설정해야 해서 ProviderManager의 생성자로 customAuthenticationProvider 을 전달하는 방식으로 처리 하였습니다.

    @Bean
    public CustomAuthenticationProcessingFilter customAuthenticationProcessingFilter() throws Exception {
        CustomAuthenticationProcessingFilter filter = new CustomAuthenticationProcessingFilter();
//         filter.setAuthenticationManager(authenticationManager(null));
        filter.setAuthenticationManager(new ProviderManager(customAuthenticationProvider));
        return filter;
    }

 

 

 

신석균님의 프로필 이미지
신석균
질문자

Spring Security가 6 에서 변경 사항이 많아 변경된 부분을 적용하여 최종적으로 최종적으로 AuthenticationConfiguration authenticationConfiguration 을 주입 받아서 등록하였습니다.

의견 주셔서 감사 하니다.

@EnableWebSecurity
@RequiredArgsConstructor
@Configuration
public class DefaultSecurityConfig {
    private final CustomAuthenticationProvider customAuthenticationProvider;
    private final CustomUserDetailsService customUserDetailsService;

    private final AuthenticationConfiguration authenticationConfiguration;


    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }
    @Bean
    public CustomAuthenticationProcessingFilter customAuthenticationProcessingFilter() throws Exception{
        CustomAuthenticationProcessingFilter filter = new CustomAuthenticationProcessingFilter();
         filter.setAuthenticationManager(authenticationManager(authenticationConfiguration));
//        filter.setAuthenticationSuccessHandler(customAuthenticationSuccessHandler());
//        filter.setAuthenticationFailureHandler(customAuthenticationFailureHandler());

        return filter;
    }
    .............
}
신석균님의 프로필 이미지
신석균

작성한 질문수

질문하기