본문 바로가기

백엔드/Spring

[SpringSecurity] Invalid CSRF token found for http://localhost:8080/jedu/user/register.do

회원가입을 진행하던 중 HTTP 403 에러가 발생하였다.

Spring Security 3.2  이후 버전에서는 적절한 CSRF 토큰을 포함시켜주지 않으면 에러를 발생하게끔 되어있다.

관련 로그
2018-10-14 18:10 [DEBUG] /user/register.do at position 1 of 14 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2018-10-14 18:10 [DEBUG] HttpSession returned null object for SPRING_SECURITY_CONTEXT
2018-10-14 18:10 [DEBUG] No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@4f72f029. A new one will be created.
2018-10-14 18:10 [DEBUG] /user/register.do at position 2 of 14 in additional filter chain; firing Filter: 'ConcurrentSessionFilter'
2018-10-14 18:10 [DEBUG] /user/register.do at position 3 of 14 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2018-10-14 18:10 [DEBUG] /user/register.do at position 4 of 14 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2018-10-14 18:10 [DEBUG] /user/register.do at position 5 of 14 in additional filter chain; firing Filter: 'CsrfFilter'
2018-10-14 18:10 [DEBUG] Invalid CSRF token found for http://localhost:8080/jedu/user/register.do


CSRF 토큰을 (쉽게) 포함시키기 위해 선행되어야 하는 작업으론..
  1. spring security taglib 선언
  2. ajax를 사용하는가?

in jsp....
<%@ taglib  uri="http://www.springframework.org/security/tags"  prefix="sec" %>

위 처럼 jsp에 taglib를 선언한다.



ajax를 사용하지 않고 form을 submit 하는 방식이라면 아래처럼..

<form class="m-0 sky-form" name="regForm" method="post" enctype="multipart/form-data">
    <sec:csrfInput />
    .........
</form>

만약 ajax를 사용한다면 <head> 태그 아래에...

<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<sec:csrfMetaTags />

CSRF 정보를 추가하는 방법이 각각 다르므로 유의해야 한다..

ajax 호출시에는 header 정보에 CSRF 정보를 넣어주어야 하는데 아래 코드와 같다.
var csrfParameter = $("meta[name='_csrf_parameter']").attr("content");
var csrfToken = $("meta[name='_csrf']").attr("content");
var csrfHeader = $("meta[name='_csrf_header']").attr("content");
var headers = {};
headers[csrfHeader] = csrfToken;

$.ajax({
    url: '<c:url value="/user/register.do" />',
    type: "POST",
    headers: headers,
    data: formData,
......
});