Spring Security CSRF 토큰 - eunja511005/Tutorial GitHub Wiki

의존성 추가

	    <!-- security 사용 위해 종속성 포함 -->
	    <dependency>
	      <groupId>org.springframework.boot</groupId>
	      <artifactId>spring-boot-starter-security</artifactId>
	    </dependency>
	    		
	    <!-- security test 사용 위해 종속성 포함 -->		
	    <dependency>
		<groupId>org.springframework.security</groupId>
		<artifactId>spring-security-test</artifactId>
		<scope>test</scope>
	    </dependency>	

CSRF 기능 사용을 위한 설정 - MyWebSecurityConfigurerAdapter.java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Configuration
@EnableWebSecurity //스프링시큐리티 사용을 위한 어노테이션선언
@RequiredArgsConstructor
@Slf4j
public class MyWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception { // http 관련 인증 설정
        /**
         * 특정 URL에 대해 csrf 토큰 체크 안하도록 설정, 
         * 기본으로 Get은 체크하지 않음, 
         * Post/Put일때는 꼭 csrf 토큰 사용 할 것
         * javascript에서 CSRF 토큰을 사용하가 위해 httpOnlyFalse()로 지정
         */
        http.csrf()
        	.ignoringAntMatchers("/logout/**")
        	.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
    }
}

jsp

[중요] form 태그에 action이 있을 경우만 hidden csrf가 자동 생성됨 (없으면 csrf 안생김)

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Add Book</title>
    </head>
    <body>
        <c:if test="${addBookSuccess}">
            <div>Successfully added Book with ISBN: ${savedBook.isbn}</div>
        </c:if>

        <c:url var="add_book_url" value="/book/addBook"/>
        <form:form action="${add_book_url}" method="post" modelAttribute="book">
            <form:label path="isbn">ISBN: </form:label> <form:input type="text" path="isbn"/>
            <form:label path="name">Book Name: </form:label> <form:input type="text" path="name"/>
            <form:label path="author">Author Name: </form:label> <form:input path="author"/>
            <input type="submit" value="submit"/>
        </form:form>
    </body>
</html>

ajax 호출시 csrf 토큰 전달 필요 시

1. jsp 파일에서 CSRF 토큰 받기
  <meta name="_csrf" content="${_csrf.token}"/>
  <meta name="_csrf_header" content="${_csrf.headerName}"/>

2. jsp 파일에 js파일에서 가져도 쓸수 있도록 변수로 선언
  <script type="text/javascript">
    var token = $("meta[name='_csrf']").attr("content");
    var header = $("meta[name='_csrf_header']").attr("content");

3. js 파일에서 ajax 호출 시 HTTP Header에 추가 해 줌
  $.ajax({
    type: "POST",
    contentType: "application/json",
    url: "/csrf/ajax",
    data: JSON.stringfy(jsonData),
    beforeSend: function(xhr){
      xhr.setRequestHeader(header, token);
    } 
  });
⚠️ **GitHub.com Fallback** ⚠️