[REST API 보안 적용]_04_스프링 시큐리티 기본 설정

2 minute read

스프링 시큐리티 기본 설정

시큐리티 필터를 적용하지 않음…

  • /docs/index.html

로그인 없이 접근 가능

  • GET /api/events
  • GET /api/events/{id}

로그인 해야 접근 가능

  • 나머지 다…
  • POST /api/events
  • PUT /api/events/{id{

스프링 시큐리티 OAuth 2.0

  • AuthorizationServer: OAuth2 토큰 발행(/oauth/token) 및 토큰 인증(/oauth/authorize)
    • Oder 0 (리소스 서버 보다 우선 순위가 높다.)
  • ResourceServer: 리소스 요청 인증 처리 (OAuth 2 토큰 검사)
    • Oder 3 (이 값은 현재 고칠 수 없음)

스프링 시큐리티 설정

  • @EnableWebSecurity
  • @EnableGlobalMethodSecurity
  • extends WebSecurityConfigurerAdapter
  • PasswordEncoder: PasswordEncoderFactories.createDelegatingPassworkEncoder()
  • TokenStore: InMemoryTokenStore
  • AuthenticationManagerBean
  • configure(AuthenticationManagerBuidler auth)
    • userDetailsService
    • passwordEncoder
  • configure(HttpSecurity http)
    • /docs/** : permitAll
  • configure(WebSecurty web)
    • ignore
      • /docs/**
      • /favicon.ico
  • PathRequest.toStaticResources() 사용하기

기존 테스트 깨짐

스프링 부트는 스프링 시큐리티를 의존성에 추가하는 순간 스프링 시큐리티용 자동설정을 적용해준다.

자동설정에 의하면,

모든 요청들은 인증이 필요해진다.

스프링 시큐리티가 사용자를 하나 인메모리에 임의로 생성해준다.

⇒ 그 결과, 이전에 만든 컨트롤러 테스트 대부분이 깨지게 된다.

스프링 시큐리티 기본 설정

스프링 시큐리티 OAuth 2.0을 적용

1. AuthorizationServer와 ResourceServer가 공통으로 사용할만한 설정을 추가해야 한다.

WebSecurityConfigurerAdapter를 상속받는 순간 더이상 스프링 부트가 제공해주는 시큐리티 설정이 적용되지 않고, 우리가 직접 정의하는 설정이 적용된다.

  • SecurityConfig 생성

2. PasswordEncoder 빈등록

※ PasswordEncoder

  • 다양한 인코딩 타입을 지원하는 패스워드 인코더
  • 어떠한 방식으로 인코딩되었는지 알 수 있도록 인코딩된 패스워드 앞에 prefix를 붙여서 알려준다.
@Configuration
public class AppConfig {
    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }
}

3. SecurityConfig 구현

  1. UserDetailsService 구현체 - “AccountService” 를 받아오기

  2. PasswordEncoder 받아오기

  3. TokenStore : OAuth 토큰을 저장. 인메모리TokenStore사용

  4. AuthorizationServer와 ResourceServer가 참조할 수 있도록 AuthenticationManager를 빈으로 노출(모든 경우에 노출할 필요는 없고 필요한 경우에만)

    빈 노출방법 → authenticationManagerBean()를 오버라이딩해서 @Bean 애노테이션을 붙이면 된다.

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
    
  5. AuthenticationManager를 어떻게 만들것인지 빌더를 재정의

    userDetailsService와 passwordEncoder를 내가 구현한 설정으로 사용하도록 등록

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
      auth.userDetailsService(accountService)
        .passwordEncoder(passwordEncoder);
    }
    

필터링 - Filter를 적용할지 여부를 WebSecurity에서 걸러낼 수 있다.

  • .ignoring() : 무시할 요청
    • index.htm
    • 정적인 리소스들 (/docs/**, /favicon.ico … )

스프링부트가 제공하는 PathRequest(servlet꺼)로 static 리소스의 기본위치를 가져와서 시큐리티가 적용되지 않도록 설정

@Override
public void configure(WebSecurity web) throws Exception {
  web.ignoring().mvcMatchers("/docs/index.html");
  // Spring Booot에서 제공해주는 static resource path
  web.ignoring().requestMatchers(PathRequest.toStaticResources().atCommonLocations());
}

⇒ 애플리케이션 실행 후 정적인 페이지 요청이 성공하는지 확인

필터링 - 스프링 시큐리티는 적용하되, http로 걸러낼 수 있다.

  • configure(HttpSecurity http)
    • /docs/** : permitAll
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .mvcMatchers("/docs/index.html").anonymous()
            .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).anonymous();
}

시큐리티 디버그 메시지를 보면, 훨씬 더 많은 동작을 하고 있다. Filter로 걸러지지 않았기 때문에 일단 스프링 시큐리티를 타게되고, 타면서 매칭이되는지 확인하는 과정이 수행된다.

이런 static리소스를 허용할 것이라면 Web에서 걸러주는 것이 서버가 조금이나마 덜 일하게 된다.

로깅 설정

logging.level.org.springframework.security=DEBUG

FilterChainProxy로 어떤 필터들이 걸려서 동작하는지 알 수 있다.


예제 에러

이번 강의(Spring Security 기본설정편)에서 WebSecurity 의 ingnore 설정들이 제대로 동작하지 않는 경우에 대해 Spring Security 관련 설정들을 모두 주석 처리하며 에러들을 다시 쭉 살펴보고 다른 분들에게 조금이라도 도움이 될까 싶어서 글 남깁니다.

(이번 강의에서 추가된 내용 한정) Security 설정 시 테스트가 거의 깨집니다

-> 테스트가 깨지는 바람에 Spring docs에 관한 패키징이 정상적으로 이루어지지 않았습니다

-> docs 관련 플러그인이 제대로 동작하지 않는 바람에 “/docs/index.html” 의 경로가 정의되지 않았습니다

-> 경로가 정의되지 않아 “/docs/index.html” 에 접근 할 시에 404 에러가 발생합니다

결론적으로 Security 설정에 정의되지 않은 경로를 ingnore 한 셈이 되어버려서 그 경로로 접근을 해도 Spring Security login 화면이 동작하는 것 같습니다. 혹시 제가 이해한 것에 잘못된 점이 있다면 피드백 주세욥.

+ 리소스서버 설정편에서 테스트 관련 에러를 전부 고치고 나니 해당 문제가 해결됐습니다