SecurityContext 구현은 리액티브 애플리케이션에서는 똑같이 작동하지 않는다. SecurityContext는 ThreadLocal에 기반을 두지만 이제 요청당 두 개 이상의 스레드가 사용된다.
SecurityContext가 달라졌기 때문에 모든 권한 부여 구성이 영향을 받는다. 권한 부여 규칙은 SecurityContext에 저장된 Authentication에 저장된 Authentication 인스턴스에 의존한다. 따라서 이제 엔드포인트 계층에 적용된 보안 구성과 전역 메서드 보안 기능이 영향을 받는다.
사용자 세부 정보를 검색하는 구성 요소인 UserDetailsService는 하나의 데이터 원본이다. 따라서 사용자 세부 정보 서비스도 리액티브 방식을 지원해야 한다.
# 리액티브 앱에서의 사용자 관리
리액티브 환경에서는 ReactiveUserDetailsService를 활용해서 사용자를 추가할 수 있다.
아래 소스를 참고
@Configuration
public class ProejctConfig {
@Bean
public ReactiveUserDetailsService reactiveUserDetailsService() {
var u = User.withUsername("john")
.password("12345")
.authorities("READ")
.build() ;
var uds = new MapReactiveUserDetailsService(u) ;
return uds ;
}
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance() ;
}
}
리액티브 환경에서의 큰 차이점은 인증 공급자가 없다. 인긍 관리자가 그 역할을 대신 수행한다.
리액티브 앱에서 스프링 시큐리티는 SecurityWebFilterChain 이라는 계약으로 구성을 적용한다.
즉, 리액티브 앱에는 SecurityWebFilterChain 형식의 빈을 스프링 컨텍스트에 추가해야 한다.
@EnableReactiveMethodSecurity -> 리액티브 메서드 보안 기능 활성화 어노테이션이다.
예시는 아래와 같다.
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
return http.authorizeExchange(exchange -> // 엔드 포인트 권한 부여 구성 시작을 의미
exchange.pathMatchers(HttpMethod.GET, "/hello")
.authenticated() // 인증해야 해당 요청에 적븐할 수 있게 구성
.anyExchange().permitAll()
).httpBasic(withDefaults())
.build() ;
}