Cross-Site Request Forgery(CSRF) 는 공격자가 사용자를 대신하여 무단으로 조작하는 흔한 웹 보안 취약점이다. Spring Boot는 Spring Security를 통하여 CSRF 공격으로부터 어플리케이션을 간단하게 보호할 수 있는 방법을 제공한다. 최근에 Security 관련설정에서 상속받아 사용하던 WebSecurityConfigurerAdapter 클래스가 Deprecate됨에 따라 설정방법에도 변화가 발생하였다.
Spring Boot Security 설정 2.X => 3.1.X 마이그레이션은 다음의 문서를 확인해 보자
https://docs.spring.io/spring-security/reference/migration-7/configuration.html
사전 구성 요소
스프링 부트 프로젝트를 구성할 때 Spring Initializr를 이용하여 다음의 디펜던시를 추가한다.
- Spring Web
- Spring Security
Step 1: Gradle Dependencies (build.gradle)
build.gradle 에 디펜던시가 다음과 같이 포함되어있는지 확인해보자.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
}
Step 2: 컨트롤러 설정
폼 화면 및 Submit 처리를 위한 컨트롤러를 간단하게 구성해보자.
@Controller
@RequestMapping("/sample")
public class SampleController {
@GetMapping("/form")
public String showForm() {
return "csrf-form";
}
@PostMapping("/submit")
public String processForm() {
return "success";
}
}
Step 3: HTML Form 구성
Thymeleaf 를 사용하여 CSRF 토큰을 포함하는 HTML form 을 생성한다. CSRF 토큰을 포함하게 되면 요청 이 어플리케이션에서 온 것인지를 확인한다. 간단히 구성해 보자. (thymeleaf 를 사용하는 경우 관련 디펜던시를 추가해야 한다.)
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>CSRF Example - Form</title>
</head>
<body>
<h1>CSRF Example</h1>
<form action="/sample/submit" method="post">
<label for="data">Data:</label>
<input type="text" id="data" name="data">
<!-- CSRF token 을 포함시킨다 -->
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
<button type="submit">Submit</button>
</form>
</body>
</html>
Step 4: Security 설정하기
Spring Security 를 활성화하고 CSRF를 구성하려면 관련 설정을 추가해야 한다. 다음과 같이 구성해보자
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize.requestMatchers(
"/sample/form"
).permitAll()
.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults())
.csrf(csrf -> csrf.csrfTokenRepository(csrfTokenRepository()));
return http.build();
}
}
Step 5: 테스트
CSRF를 구현한 후에 어플리케이션을 테스트 하는것이 중요하다. Form 이 CSRF 토큰을 포함하는 지 확인하고, CSRF 토큰 유효성 검사가 정상적으로 작동하는지 확인해 보자.

Spring Security 에서 CSRF 대응 방법에 대하여 간단하게 살펴보았다.