[REST API 보안 적용]_04_스프링 시큐리티 기본 설정
스프링 시큐리티 기본 설정
시큐리티 필터를 적용하지 않음…
- /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
- ignore
- 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
구현
-
UserDetailsService 구현체 - “AccountService” 를 받아오기
-
PasswordEncoder 받아오기
-
TokenStore : OAuth 토큰을 저장. 인메모리TokenStore사용
-
AuthorizationServer와 ResourceServer가 참조할 수 있도록 AuthenticationManager를 빈으로 노출(모든 경우에 노출할 필요는 없고 필요한 경우에만)
빈 노출방법 → authenticationManagerBean()를 오버라이딩해서 @Bean 애노테이션을 붙이면 된다.
@Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); }
-
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 화면이 동작하는 것 같습니다. 혹시 제가 이해한 것에 잘못된 점이 있다면 피드백 주세욥.
+ 리소스서버 설정편에서 테스트 관련 에러를 전부 고치고 나니 해당 문제가 해결됐습니다