티스토리 뷰
Spring Boot WebFlux - Multipart(multipart/form-data) 전송시 Security CSRF(XSRF) Filter 설정
최서리나리 2019. 7. 24. 13:47WebFlux로 프로젝트를 진행하던 중, Multipart로 전송시 Spring Security에 설정한 CSRF 관련 사항과 충돌이 발생하여 이에대한 대응책을 남긴다.
(invalid csrf token)
Multipart의 경우 FormData가 ServerRequest에 QueryParameter로 들어오지 않기 때문에,
클라이언트 - CSRF Filter 사이에 중개필터를 하나 두고 필터 순서를 변경하여 CSRF관련 작업을 처리해야 한다.
작업순서는 아래와 같다.
1. 중개필터 작성
2. Spring Security에 중개필터 추가 (Filter Order는 CSRF Filter 이전에 위치하도록 순서지정)
먼저 중개필터를 작성한다.
@Component
public class MultipartCsrfFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange serverWebExchange,
WebFilterChain webFilterChain) {
if(!HttpMethod.GET.equals(serverWebExchange.getRequest().getMethod())){
return serverWebExchange.getMultipartData().flatMap(v -> {
Map<String, Part> map = v.toSingleValueMap();
if(map.get("_csrf") != null){
serverWebExchange.getRequest()
.mutate()
.header("X-CSRF-TOKEN", ((FormFieldPart) map.get("_csrf")).value())
.build();
}
return webFilterChain.filter(serverWebExchange);
});
}else{
return webFilterChain.filter(serverWebExchange);
}
}
}
Security 설정시 별다른 설정을 하지 않았다면 default token repository인 WebSessionServerCsrfTokenRepository 클래스의 정보를 따라간다.
- WebSessionServerCsrfTokenRepository
public class WebSessionServerCsrfTokenRepository implements ServerCsrfTokenRepository {
private static final String DEFAULT_CSRF_PARAMETER_NAME = "_csrf";
private static final String DEFAULT_CSRF_HEADER_NAME = "X-CSRF-TOKEN";
private static final String DEFAULT_CSRF_TOKEN_ATTR_NAME = WebSessionServerCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN");
private String parameterName = "_csrf";
private String headerName = "X-CSRF-TOKEN";
private String sessionAttributeName;
...
}
위 소스코드를 보다시피, default header name은 'X-CSRF-TOKEN'이며 paramater name은 '_csrf'이다.
변경사항이 있다면 그에따라 필터의 내용도 변경하면 될 것이다.
중개필터의 내용은 단순히 GET요청이 아니면서, _csrf로 들어온 parameter가 있을 경우 헤더에 CSRF값을 담아주고
다음필터로 넘기는 내용이다.
다음은 Security설정이다.
@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
@ComponentScan(basePackages = {........})
public class SecurityConfiguration {
// custom manager
@Autowired
private AuthenticationManager authenticationManager;
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
return http.authorizeExchange()
... ...
.addFilterAt(new MultipartCsrfFilter(), SecurityWebFiltersOrder.FIRST)
.csrf()
.and()
.build();
}
}
ServerHttpSecurity의 addFilterAt 함수를 통해 중개필터를 등록한다.
이때 필터 순서는 가장 먼저 올 수 있도록 지정
위와같이 작성하고 실행하면 다음과 같이 프로세스가 흘러감을 알 수 있다.
- MultipartCsrfFilter
- CsrfWebFilter
이렇게 WebFlux환경에서의 Multipart CSRF검증 로직은 끝이난다.
Security 설정 부분에서 Filter 순서를 변경하지 않았다면 CsrfWebFilter가 상위에 위치하기 때문에 403 status와 함께 invalid csrf token가 출력되며,
중개필터에서 헤더에 올바른 token name을 넣지 않았다면 마찬가지로 CsrfWebFilter에서 토큰을 찾지 못했으므로 invalid csrf token가 출력되게 된다.
'개발 이야기 > SPRING' 카테고리의 다른 글
- Total
- Today
- Yesterday
- SpringDataJPA
- Spring Security
- JPA
- Spring Boot
- 친환경차
- Weblogic
- 스프링
- hibernate
- 저공해자동차
- Util
- SI
- 국비교육
- multipart
- Spring Cache
- memcached
- WebFlux
- 취업
- Thymeleaf
- Java
- Spring
- intellij
- spring webflux
- 저공해자동차 스티커
- spring-data-jpa
- query-dsl
- CSRF
- spring-jpa
- 이직
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |