Spring Webflux 및 MVC Security환경 비교
2023. 7. 15. 14:05ㆍSpring/webflux
728x90
개인적으로 느끼기에는 구조 자체는 MVC 환경 Security와 비슷하다.
허나 반환 형식이랑 체인 설정법만 조금씩 다른 느낌이다.
SecurityConfig
MVC 환경
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public class SecurityConfig {
JwtAuthenticationFilter jwtAuthenticationFilter;
@Bean
public SecurityFilterChain configure(HttpSecurity http) throws Exception {
return http.authorizeHttpRequests(this::match)
.addFilterAfter(jwtAuthenticationFilter, BasicAuthenticationFilter.class)
.cors(c -> c.configurationSource(corsConfigurationSource()))
.csrf(AbstractHttpConfigurer::disable)
.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedMethod("*");
config.addAllowedOrigin("https://*");
config.addAllowedHeader("*");
config.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
public AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry
match(
AuthorizeHttpRequestsConfigurer<HttpSecurity>
.AuthorizationManagerRequestMatcherRegistry
r) {
return r.anyRequest().authenticated();
}
}
Webflux 환경
@Configuration
@EnableWebFluxSecurity
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
@RequiredArgsConstructor
public class WebfluxSecurityConfig {
WebfluxAuthFilter webfluxAuthFilter;
@Bean
public SecurityWebFilterChain configure(ServerHttpSecurity http) {
return http.authorizeExchange(getAuthorizeExchangeSpecCustomizer())
.csrf(ServerHttpSecurity.CsrfSpec::disable)
.addFilterBefore(webfluxAuthFilter, SecurityWebFiltersOrder.AUTHENTICATION)
.cors(c -> c.configurationSource(corsConfigurationSource()))
.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedMethod("*");
config.addAllowedOrigin("https://**");
config.addAllowedHeader("*");
config.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
private Customizer<ServerHttpSecurity.AuthorizeExchangeSpec>
getAuthorizeExchangeSpecCustomizer() {
return r -> r.pathMatchers("/**").permitAll();
}
}
차이점
MVC | Webflux | |
annotation | @EnableWebSecurity 사용 | @EnableWebFluxSecurity 사용 |
cors ConfigurationSource | cors 하위 패키지 요소 사용 | cors.reactive 하위 패키지 요소 사용 |
SecurityFilterChain | HttpSecurity.authorizeHttpRequest | ServerHttpSecurity.authorizeExchange |
생각보다 두 구조가 비슷한 것을 확인할 수 있다
Filter
Fliter 구조 또한 비슷한 것을 확인할 수 있다.
개인적으로 다양한 레퍼런스를 확인해봤을 때, MVC 환경에서는 다양한 Filter을 extends 해서 사용하는 경향이 있고, Webflux 환경에서는 WebFilter를 직접 구현해서 사용하는 경향이 있는 것 같다
아래 예시는 @Override 부분 구조만 확인해보면 좋을듯하다.
MVC 환경
@RequiredArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
public class JwtAuthenticationFilter extends OncePerRequestFilter {
JwtExtractor extractor;
FilterExclusionValidator exclusionValidator;
@Override
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
final String token = request.getHeader("Authorization");
final AuthUser auth = new AuthUser(extractor.extract(token));
SecurityContextHolder.getContext().setAuthentication(auth);
filterChain.doFilter(request, response);
}
@Override
protected boolean shouldNotFilter(HttpServletRequest request) {
return exclusionValidator.validate(request.getServletPath());
}
}
Webflux 환경
@Component
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
@RequiredArgsConstructor
public class WebfluxAuthFilter implements WebFilter {
JwtExtractor jwtExtractor;
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
final JwtPayload payload = getJwtPayload(exchange.getRequest());
return chain.filter(exchange)
.contextWrite(
ReactiveSecurityContextHolder.withAuthentication(new AuthUser(payload)));
}
private JwtPayload getJwtPayload(final ServerHttpRequest request) {
final String token = request.getHeaders().getFirst("Authorization");
return jwtExtractor.extract(token);
}
}
차이점
MVC | Webflux | |
filter 반환 형태 | void | Mono<Void> |
다음 필터 실행 | filterChain.doFilter(req,res) | WebFilterChain.filter(exchange) |
SecurityContext 접근 및 Auth설정 | SCH.getContext().setAuth...(auth) | RSCH.withAuthentication(auth) |
보시다시피 webflux 환경에서는 어떠한 흐름을 반환하는(Publisher를 반환하는) 구조로 되어있다.
Controller단에서 Principal 가져오기
MVC 환경
@RestController
public class Controller {
@GetMapping
public void getUser(Authentication auth) {
auth.getName();
}
}
Webflux 환경
@RestController
public class WebfluxController {
@GetMapping
public Mono<void> match(Mono<Authentication> auth) {
return matchService.subscribe(auth.map(Authentication::getName));
}
}
반환 형태가 기존 Authentication에서 Mono로 wrapping 한 것 외에 차이점이 없다.
728x90
'Spring > webflux' 카테고리의 다른 글
Spring webflux를 활용한 SSE(Server Sent Event) 구현 (0) | 2023.07.15 |
---|---|
Spring Webflux - Scheduler (0) | 2023.07.15 |
Spring Webflux Sink (0) | 2023.07.15 |
리액티브 스트림즈, Mono, 그리고 Flux (0) | 2023.07.14 |
Reactive programming - Spring webflux (0) | 2023.07.14 |