• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    미해결

커스텀 provider와 시큐리티의 provider 함께 사용하기

24.01.31 23:46 작성 24.01.31 23:47 수정 조회수 260

0

안녕하세요.

커스텀 provider와 시큐리티의 provider 함께 사용하는 방법을 도저히 못찾겠습니다.

 

  1. 커스텀 필터와 커스텀 provider를 시큐리티 필터체인에 등록

  2. 커스텀 필터에서 인증되지 않은 사용자 요청은 http basic 방식으로 인증

위 요구사항을 충족시키기 위해서 스프링 시큐리티에서 기본적으로 제공하는 provider 리스트와 커스텀 provider를 providerManager가 갖고 있도록하고 싶은데요.

저의 커스텀 provider를 bean으로 등록하면 시큐리티에서 제공되는 모든 provider는 providerManager가 갖고 있지 않더라구요. 그래서 AuthenticationManagerBuilder를 통해서 커스텀 provider를 추가하는 방식으로 했는데도...디버깅 모드에선 커스텀 provider만 등록되 상태입니다... 어떻게해야할까요??

 

@Component 로 빈으로 등록한 커스텀 provider를 주입받고 해당 provider를 authenticationManagerBuilder.authenticationProvider(this.authenticationProvider); 를 통해 추가만 하려고했습니다....

 

고견부탁드립니다.. 해결이 안됩니다!!ㅜㅜ

 

@Configuration

public class SecurityConfiguration {

private static final String CLIENT_ID_HEADER_NAME = "X-CLIENT-ID";

private static final String API_KEY_HEADER_NAME = "X-API-KEY";

private final AuthenticationProvider authenticationProvider;

public SecurityConfiguration(AuthenticationProvider authenticationProvider) {

this.authenticationProvider = authenticationProvider;

}

@Bean

SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);

authenticationManagerBuilder.authenticationProvider(this.authenticationProvider);

http.csrf(CsrfConfigurer::disable)

.cors(CorsConfigurer::disable)

.formLogin(FormLoginConfigurer::disable)

.httpBasic(Customizer.withDefaults());

http.authorizeHttpRequests(request -> request.anyRequest().authenticated());

http.addFilterAfter(requestHeaderAuthenticationFilter(http), HeaderWriterFilter.class);

return http.build();

}

@Bean

RequestHeaderAuthenticationFilter requestHeaderAuthenticationFilter(HttpSecurity http) throws Exception {

RequestHeaderAuthenticationFilter filter = new RequestHeaderAuthenticationFilter();

filter.setPrincipalRequestHeader(CLIENT_ID_HEADER_NAME);

filter.setCredentialsRequestHeader(API_KEY_HEADER_NAME);

filter.setExceptionIfHeaderMissing(false);

filter.setAuthenticationManager(authenticationManager(http));

return filter;

}

@Bean

AuthenticationManager authenticationManager(HttpSecurity http) throws Exception {

AuthenticationManagerBuilder authenticationManagerBuilder =

http.getSharedObject(AuthenticationManagerBuilder.class);

return authenticationManagerBuilder.build();

}

@Bean

InMemoryUserDetailsManager inMemoryUserDetailsManager() {

UserDetails admin = User.withUsername("admin").password("admin").build();

return new InMemoryUserDetailsManager(admin);

}

}

답변 2

·

답변을 작성해보세요.

0

답변이 조금 늦었습니다.

전체 소스를 공유해 주시면 제가 테스트 하고 답변 드리도록 하겠습니다.

0

인프런 AI 인턴님의 프로필

인프런 AI 인턴

2024.02.02

안녕하세요, 인프런 AI 인턴입니다.
이화평님, 스프링 시큐리티에서 기본적으로 제공하는 AuthenticationProvider와 사용자 정의 AuthenticationProvider를 함께 사용하고 싶으시군요.

제공된 정보를 바탕으로, 여러분이 UserDetailsService 빈을 등록할 경우 기본적으로 제공되는 InMemoryUserDetailsManager 빈은 생성되지 않는다는 점에 착안하여 해결책을 모색해볼 수 있습니다. 여러분의 설정에서 InMemoryUserDetailsManager를 직접 빈으로 등록하셨듯이, 사용자 정의 AuthenticationProvider도 빈으로 등록하신 후 AuthenticationManagerBuilder에 추가하는 접근 방식을 취하셨네요. 이것은 올바른 시작입니다.

그러나 AuthenticationProvider만을 AuthenticationManagerBuilder에 등록하였을 때 기본 제공되는 AuthenticationProvider들이 사라지는 문제가 발생하고 있습니다. 일반적으로 자신만의 AuthenticationProvider를 추가할 때에는 AuthenticationManagerBuilder에 추가하기 전에, 빌더가 기본 AuthenticationProvider들을 포함하도록 구성해야 합니다.

해결 방법으로는 AuthenticationManagerBuilder에 여러분의 AuthenticationProvider를 추가하는 것 이전에, 기본적으로 사용되는 AuthenticationProvider를 추가해야 합니다. 이를 위해 configure(AuthenticationManagerBuilder auth) 메소드를 오버라이드하는 방법을 시도해볼 수 있습니다. 이 메소드 내에서 auth.authenticationProvider()를 호출하여 사용자 정의 AuthenticationProvider를 추가함과 동시에, 원하는 기본 AuthenticationProvider들을 구성할 수 있습니다.

추가적으로, AuthenticationManager를 별도로 빈으로 등록하는 것보다는 AuthenticationManagerBuilder를 통해 필터에서 참조할 수 있도록 하는 것이 더 일반적인 방법입니다. AuthenticationManager를 필요로 하는 필터에 직접 참조를 제공하기 위한 방법으로 authenticationManagerBuilder.build()를 호출하게 됩니다.

참고로 이미지 URL과 정보 출처 URL은 제공되지 않았기 때문에 직접적인 문서 참조를 위한 URL은 언급하지 않았습니다.

다음은 스프링 시큐리티 문서에서 관련 정보를 참조하는 예시입니다:

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    // ... 기존 코드 ...

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 1. 기본 AuthenticationProvider 등록
        // 예) auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);

        // 2. 사용자 정의 AuthenticationProvider 등
        auth.authenticationProvider(customAuthenticationProvider);

        // 기타 설정 ...
    }

    // ... 기존 코드 ...
}

위 코드는 확장성과 유지보수성을 고려하여 WebSecurityConfigurerAdapter를 사용한 예시이며, 실제 상황에 맞게 변형하여 사용하시기 바랍니다.