[Spring]CSRF 토큰이 Multipart 이미지 전송에서 인식되지 않는 이슈 해결 방법(Error Message : Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.)
서론
Spring 프로젝트를 진행하던 중 이미지 전송을 위해 enctype="multipart/form-data"인 form 태그 안에 아래와 같이 CSRF 토큰을 기술해도 Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.이라는 에러 메시지가 나타나며 인식하지 못하는 에러가 발생했습니다. 이번 포스팅에서는 이에 대한 해결 방법을 다뤄보려 합니다.
<form action="/url" method="post" enctype="multipart/form-data">
<input type="hidden" name="${_csrf.parameterName }" value="${_csrf.token }" />
</form>
본론
multipart/form-data 전송에서 CSRF 토큰을 사용하기 위해선 Spring Framework에 구현된 MultipartFilter 기능을 활성화해야 합니다.
[테스트 환경]
Spring 4.3.12
Apache Commons FileUpload 라이브러리 사용
https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload
[해결 방법]
1. tomcat의 context.xml에 기술된 Context 태그 안에 allowCasualMultipartParsing 속성을 true로 설정
[context.xml]
<Context allowCasualMultipartParsing="true" path="/">
<Resources cachingAllowed="true" cacheMaxSize="100000" />
<!-- Default set of monitored resources. If one of these changes, the -->
<!-- web application will be reloaded. -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
</Context>
2. web.xml에 아래 예제처럼 springSecurityFilterChain보다 반드시! 앞에 MultipartFilter 추가 (앞에 추가하지 않으면 동일하게 CSRF토큰 인식 불가능 에러가 발생함.)
[web.xml]
<filter>
<display-name>springMultipartFilter</display-name>
<filter-name>springMultipartFilter</filter-name>
<filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>springMultipartFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
위의 설정들을 해주고 나면 CSRF 토큰이 Mutipart 전송에서도 제대로 인식하게 됩니다.
결론
CSRF 토큰을 Mutipart 전송에서 사용하기 위해선 MultipartFilter가 필요한 걸 알게 된 좋은 경험이었습니다. 구현된 자세한 소스는 아래 링크에서 확인하실 수 있습니다.
https://github.com/GoldSwan/PictureRepository