Spring프로젝트에서 2가지 방식으로 인증을 해야하는 경우가 있었다.
root path를 구분지어서 /server 로 들어오는 요청은 appkey라는 파라미터를 통해 인증을 진행하고 싶었고,
/api로 들어오는 요청은 JWT토큰을 통해 사용자 인증을 진행하고 싶었다.
먼저 Spring security가 뭔지 간단히 알아보자.
@Configuration
@EnableWebSecurity
class WebSecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http.authorizeRequests()
.antMatchers("/home").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic()
}
@Bean
override fun userDetailsService(): UserDetailsService {
val user = User.withUsername("user")
.password("{bcrypt}\$2a\$10\$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG")
.roles("USER")
.build()
return InMemoryUserDetailsManager(user)
}
}
@EnableWebSecurity어노테이션을 통해서 Spring security에 필요한 설정들을 활성화 할 수 있고, 세부적인 설정들을 구현하려면 WebSecurityConfigurerAdapter를 상속받아서 각 기능에 맞는 메서드를 구현하면 된다.
configure(HttpSecurity)메서드를 통해서 path별로 어떤 권한/인증을 적용할지 설정할 수 있다.
UserDetailsService는 입력받은 인증정보를 기반으로 사용자 정보를 가져오는 역할을 하는 서비스인데, 여기서는 테스트용이기 때문에 메모리에 사용자정보를 미리 만들어놓는 InMemoryUserDetailsManager를 사용했다.
사실 어려운 부분은 없이 WebSecurityConfigurer를 두번 정의해주면 된다.
다만 custom filter를 정의하면서 문제가 있었는데, filter를 bean으로 등록했더니 spring에서 자동으로 필터를 등록하면서 문제가 되었었다.
filter를 bean으로 등록하지 말자
@Configuration
@EnableWebSecurity
class WebSecurityConfig {
@Order(1)
@Configuration
class InternalSecurityConfiguration: WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http
.antMatcher("/server")
.csrf().disable()
.formLogin().disable()
.httpBasic().disable()
.addFilterBefore(serverTokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter::class.java)
.authenticationProvider(preAuthProvider())
.authorizeRequests()
.anyRequest().authenticated()
}
}
@Order(2)
@Configuration
class SecurityConfiguration : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http
.requestMatchers { requestMatchers ->
requestMatchers
.antMatchers("/api")
}
.cors()
.and()
.csrf().disable()
.formLogin().disable()
.httpBasic().disable()
.addFilterBefore(jwtTokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter::class.java)
.authenticationProvider(jwtAuthProvider())
.authorizeRequests()
.anyRequest().authenticated()
}
}
}