Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN' 에러
스프링 시큐리티에서 CSRF(Cross-site Request Forgery) 보안 기능을 사용할 때 발생하는 에러
보안 기능이 동작하지 않아 발생하거나 설정이 잘못되어 발생할 수 있음
에러 발생 원인
이 에러는 주로 CSRF 토큰 값이 전달되지 않았거나, 전달된 토큰 값이 유효하지 않을 때 발생함
스프링 시큐리티에서는 CSRF 보안 기능을 사용할 때, 사용자의 세션에 저장된 CSRF 토큰 값과 요청으로 전달된 CSRF 토큰 값을 비교하여 일치하지 않으면 이 에러를 발생시킴
해결 방법
CSRF 보안 기능 해제
가장 간단한 해결책은 CSRF 보안 기능 해제
이 방법은 보안 취약점을 유발할 수 있기에 권장되는 방법은 아니지만, 개발 단계에서 CSRF 보안 기능을 잠시 해제하여 개발 편의성을 높이기 위해 사용하기에는 괜찮을 수 있음
예시
@Configuration
@EnableWebSecurity
public class SecurityConfig implements WebSecurityConfigurer<WebSecurity> {
@Autowired
private DataSource dataSource;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasRole("USER")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll()
.and()
.csrf().disable();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("SELECT username, password, enabled FROM users WHERE username = ?")
.authoritiesByUsernameQuery("SELECT username, authority FROM authorities WHERE username = ?");
}
}
CSRF 토큰 값을 전달하기
CSRF 토큰 값을 전달하는 방법
- 폼(form) 데이터에서 CSRF 토큰 값을 함께 전달하는 방법
- AJAX 요청에서 CSRF 토큰 값을 HTTP 헤더(X-CSRF-TOKEN)에 포함하여 전달하는 방법
- CSRF 토큰 값을 JavaScript로 읽어와 요청 시 함께 전달하는 방법
이 중에서 가장 일반적인 방법은 폼 데이터에서 CSRF 토큰 값을 함께 전달하는 방법임
스프링 시큐리티에서는 CSRF 토큰 값을 함께 전달해야 함
그렇지 않으면 'null' 에러가 발생할 수 있음
폼(form) 데이터에서 CSRF 토큰 값을 함께 전달하는 방법 👇
<form method="post" th:action="@{/user}">
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
<!-- other form fields -->
<button type="submit">Submit</button>
</form>
AJAX 요청에서 CSRF 토큰 값을 HTTP 헤더(X-CSRF-TOKEN)에 포함하여 전달하는 방법 👇
$(document).ready(function() {
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function(e, xhr, options) {
xhr.setRequestHeader(header, token);
});
});
CSRF 토큰 값을 JavaScript로 읽어와 요청 시 함께 전달하는 방법 👇
function sendCsrfToken(xhr, settings) {
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
xhr.setRequestHeader(header, token);
}
$.ajaxSetup({
beforeSend: sendCsrfToken
});
'프로그래밍 > Spring Boot' 카테고리의 다른 글
[Spring Boot] @DeletedMapping에서 @RequestBody 사용? (0) | 2023.05.16 |
---|---|
[Spring Boot Error] Request method 'PUT' is not supported (0) | 2023.05.04 |
[SpringBoot Error] error: Cask 'adoptopenjdk11' is unavailable (0) | 2023.02.23 |
[Spring boot] @NotNull, @NotEmpty, @NotBlank 차이 (0) | 2022.12.01 |
[Gradle Error] Cannot load driver class: org.mariadb.jdbc.Driver Error (0) | 2022.11.29 |