[TIL][Spring] multipart form 전송시 CSRF 토큰이 null인 경우(Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN')

😅 기존에 만들어 두었던 프로젝트에 spring security를 추가하는 작업 중이기 때문에 순간순간 에러를 맞이 한다....
다시 한번 과거 나의 이마를 빡빡 때리며,,,,8ㅁ8,,,후,,,괜찮아 할 수 있어...

참고 : https://goldswan.tistory.com/43


1. 에러 확인

게시글 작성 form의 형태가 multipart 타입이어서인지 글 작성시 Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN' 라는 에러를 확인할 수 있었다.
signin 페이지에서처럼 <input type="hidden" name="${_csrf.parameterName }" value="${_csrf.token }" />으로 추가해주면 간단하게 해결 될 줄 알았지만..^^ 택도 없었다.
구글링 결과 딱 내가 원하는 게시글이 있어, 참고해서 문제를 해결해보겠다.

작성 화면

에러 화면

기존 코드

<form action="write" method="post" id="insertNewContent" enctype="multipart/form-data">
	<div class="container">
		<table class="table table-borderless">
			<!--중략-->
		</table>
		<div style="text-align: center;">
			<input type="submit" class="btn btn-dark" id="insert" value="작성">
			<button class="btn btn-light" onclick="history.back(-1)">취소</button>
		</div>
	</div>
</form>

2. 해결 하기

우선 참고한 블로그 외에 더 찾아보니 multipart/form-data로 파일을 업로드 하는 경우 FilterChain(web.xml에 넣어준)을 타지 않는 제약 사항이 발생한다고 한다.
그래서 이 경우에는 springMultipartFilter를 springSecurityFilterChain 앞에 넣어줘야 한다고 한다.

tomcat 폴더 내 context.xml 수정하기

기존에는 Context 태그에 아무것도 없는 상태였지만 allowCasualMultipartParsing 속성을 추가하고 path도 추가한 후, Resources 태그도 추가해 주었다.(안해도 상관 없다고 한다.)

<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>

web.xml에 filter 추가하기

<!-- multipart filter 추가하기 -->
	<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>

	<!-- spring security filter 추가하기 -->
	<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>

form에 csrfInput 추가하기

csrfInput을 추가하지 않으면 계속 token null 에러가 나기 때문에 추가해준다.

<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
  
<form action="write" method="post" enctype="multipart/form-data">
	<sec:csrfInput/>
<!--중략-->
</form>

작성 화면

결과 화면

잘 등록되는 것을 확인할 수 있다.
(물론 중간에 이런 저런 에러들을 만나서 시간이 좀 걸렸지만^^)

좋은 웹페이지 즐겨찾기