Spring/스프링 기반 REST API 개발
[스프링 기반 REST API 개발] 시큐리티 기본 설정하기
주멘이
2021. 1. 9. 13:07
시큐리티 필터를 적용하기 않음
- /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: 리소스 요청 인증 처리 (OAuth2 토큰 검사)
- Oder 3 (이 값은 현재 고칠 수 없음)
스프링 시큐리티 설정
@EnableWebSecurity, @EnableGlobalMethodSecurity
extends WebSecurityConfigurerAdapter
- SecurityConfig @Configuration class에서 설정
- 설정하는 순간, 스프링 부트가 제공하는 자동 설정은 더 이상 제공되지 않음(커스터마이징 활성화)
- WebSecurityConfigurerAdapter를 상속받은 커스텀 설정을 빈으로 등록하면 스프링 부트의 기본 시큐리티 설정은 사용하지 않게 된다.
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {}
PasswordEncoder: PasswordEncoderFactories.createDelegatingPassworkEncoder()
- 다양한 인코딩 타입을 지원하며, 인코딩 타입을 PREFIX로 붙여준다.
@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
TokenStore: InMemoryTokenStore
@Bean
TokenStore tokenStore() {
return new InMemoryTokenStore();
}
AuthenticationManagerBean
- 다른 AuthorizationServer나 ResourceServer가 참조할 수 있도록 Bean으로 등록
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
configure(AuthenticationManagerBuidler auth)
AuthenticationManager를 재정의
- userDetailsService : accountService를 적용한다
- passwordEncoder
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(accountService)
.passwordEncoder(passwordEncoder);
}
configure(WebSecurty web)
스프링 시큐리티 필터를 타기 전에 적용된 패턴을 걸러내서 서버 부하를 줄일 수 있다.(정적 리소스들을 걸러 줄 것을 권장)
PathRequest.toStaticResources() 사용하기
- ignore
- /docs/**
- /favicon.ico
/* filter를 적용할지 말지 결정 (Http로 가기전에, WebSecurity를 적용할지 말지)- static resource 허용하기*/
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().mvcMatchers("/docs/index.html");
web.ignoring().requestMatchers(PathRequest.toStaticResources().atCommonLocations());
}
configure(HttpSecurity http)
스프링 시큐리티는 허용하면서(필터체인 안으로) HTTP로 거른다.
- /docs/**: permitAll
/* filterchain 안에서 거르기*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.anonymous()
.and()
.formLogin()
.and()
.authorizeRequests()
.mvcMatchers(HttpMethod.GET, "/api/**").authenticated()
.anyRequest().authenticated();
}
SecurityConfig 전체 코드
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private AccountService accountService;
private PasswordEncoder passwordEncoder;
@Autowired
public SecurityConfig(AccountService accountService, PasswordEncoder passwordEncoder) {
this.accountService = accountService;
this.passwordEncoder = passwordEncoder;
}
@Bean
TokenStore tokenStore() {
return new InMemoryTokenStore();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(accountService)
.passwordEncoder(passwordEncoder);
}
/* filter를 적용할지 말지 결정 (Http로 가기전에, WebSecurity를 적용할지 말지)- static resource 허용하기*/
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().mvcMatchers("/docs/index.html");
web.ignoring().requestMatchers(PathRequest.toStaticResources().atCommonLocations());
}
/* filterchain 안에서 거르기*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.anonymous()
.and()
.formLogin()
.and()
.authorizeRequests()
.mvcMatchers(HttpMethod.GET, "/api/**").authenticated()
.anyRequest().authenticated();
}
}
application.properties에 시큐리티 로그 설정
logging.level.org.springframework.security=DEBUG