티스토리 뷰

spring security는 쓰레드로컬 기반으로 동작하기 때문에 reactive 환경에서는 사용하기 힘들다. 그렇다면 reactive 환경에서는 security를 사용하지 않는걸까?
이번에는 reactive 환경에서 security를 어떻게 사용하는지 알아보자.
SecurityFilterChain
servlet stack에서는 Servlet Filter를 사용하는데, Filter Chain 중간에 DelegatingFilterProxy를 추가하고, DelegatingFilterProxy는 내부적으로 여러 개의 Security Filter를 갖는 SecurityFilterChain을 호출한다.
FilterChain내에서는 bean을 사용하기 힘들지만, SecurityFilterChain은 Spring Context를 갖기 때문에 bean에 접근이 가능하다.

SecurityWebFilterChain
reactive stack에서는 HttpWebHandlerAdapter의 WebFilter를 사용한다. HttpWebHandlerAdapter에서는 WebFilter를 등록하고, 등록된 WebFilter를 거쳐 마지막에 WebHandler로 요청이 전달되는 구조로 되어 있다.
WebFilter를 구현한 WebFilterChainProxy는 내부적으로 여러 개의 SecurityWebFilter로 구현되어 있고, servlet stack의 DelegatingFilterProxy와 동일한 역할을 한다.

ReactiveSecurityContextHolder
ReactiveSecurityContextHolder는 SecurityContextHolder와 비슷하지만, ThreadLocal 대신 context로 SecurityContext를 제공한다.(context를 사용하면 파이프라인 내부에서 어디서든 request에 접근할 수 있다.)
그렇다는 것은 context에 SecurityContext를 넣으면 쭉 전파될 것임을 보장할 수 있다는 것이다.
getContext
: SecurityContext를 Mono 형태로 제공clearContext
: SecurityContext를 clearwithSecurityContext
: securityContext를 Mono로 받고 이를 포함하는 Reactor context 반환withAuthentication
: security Authentication을 받고 SecurityContext를 받아서 이를 포함하는 Reactor context 반환
간단한 SecurityWebFilter 예제 코드
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
String iam = exchange.getRequest().getHeaders().getFirst("X-I-AM");
if (iam == null) {
final ServerHttpResponse resp = exchange.getResponse();
resp.setStatusCode(HttpStatus.UNAUTHORIZED);
return resp.setComplete();
}
Authentication authentication = new CustomAuthentication(iam);
return chain.filter(exchange)
.contextWrite(ctx ->
ReactiveSecurityContextHolder.withAuthentication(authentication);
}
- 헤더를 분석하여 X-I-AM에서 값을 추출하고, 값이 비었다면 401 status 반환한다.
- 값이 비어있지 않다면 CustomAuthentication을 생성하고, ReactiveSecurityContextHolder의 withAuthentication을 사용해서 context를 주입한다.
@GetMapping("/hello")
public Mono<String> greet() {
return ReactiveSecurityContextHolder
.getContext()
.map(securityContext ->
securityContext.getAuthentication().getPrincipal())
.flatMap(principal ->
Mono.just("Hello, " + ((Principal)principal).getName()));
- Controller에서 ReactiveSecurityContextHolder의 getContext를 이용해서 securityContext에 접근하고, 이를 이용해서 응답을 생성한다.
'Spring' 카테고리의 다른 글
[Spring] 커넥션 풀 이해하기 (0) | 2024.12.23 |
---|---|
[Spring] JDBC와 데이터베이스 접근 이해하기 (0) | 2024.12.21 |
[Spring Webflux] WebClient (0) | 2024.05.08 |
[Spring Webflux] Functional Endpoints (0) | 2024.05.07 |
[Spring Webflux] DispatcherHandler (0) | 2024.05.06 |
- Total
- Today
- Yesterday
- 코테
- leetcode
- 리팩토링
- webflux
- 자료구조
- kotlin
- 스프링부트
- mysql 8.0
- 스프링
- 그리디
- 인프런
- Spring
- 파이썬
- Real MySQL
- spring boot
- MySQL
- 구현
- 김영한
- 스프링 부트
- 백준
- 문자열
- 코틀린
- 노마드코더
- 릿코드
- 북클럽
- Algorithm
- 정렬
- 노마드
- 알고리즘
- 데이터베이스
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |