08.csrf 설정
csrf
- CSRF(Cross-Site Request Forgery)는 요청을 위조하여 사용자가 원하지 않아도 서버측으로 특정 요청을 강제로 보내는 방법
- 예) 회원 정보 변경, 게시글 CRUD를 사용자 모르게 요청 등등…
개발환경에서 csrf disable()
- 개발 환경에서는 SecurityConfig 클래스를 통해 csrf설정을 disable 설정을 한다.
- disable 설정을 하지않으면 올바른 로그인 정보를 입력하였다 하더라도 csrf 토큰을 보내지 않기 때문에 로그인이 되지 않는다
- 배포에서는 csrf를 enable하게 하고 추가 설정을 해줘야 한다
- 기본이 enable 이므로 disable 하지 않으면 된다
- enable 설정 시 시큐리티는 POST, PUT, DELETE 요청에 대해서 토큰 검증을 진행한다.
- POST 요청 시 form에 토큰을 추가하여 보내도록 한다
1
2
3
4
5
6
<form action="/loginReceiver" method="post" name="loginForm">
<input type="text" name="username" placeholder="아이디"/>
<input type="password" name="password" placeholder="비밀번호"/>
<input type="hidden" name="_csrf" value=""/>
<input type="submit" value="로그인"/>
</form>
- ajax와 같은 비동기 통신에서는 <head> 태그에 요소를 추가하여 요청한다
- XMLHttpRequest 요청 시 setRequestHeader를 통해 _csrf , _csrf_header 의 Key에 대한 토큰 값을 넣어 요청한다
1
2
<meta name="_csrf" content=""/>
<meta name="_csrf_header" content=""/>
- GET 방식의 로그아웃을 진행할 경우
- csrf 설정 시 POST 요청으로 로그아웃을 진행해야 하지만 GET 방식으로 요청할 경우 SecurityConfig에서 추가 설정이 필요하다
1
2
3
4
5
6
7
8
9
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception{
http
.logout((auth) -> auth.logoutUrl("/logout")
.logoutSuccessUrl("/"));
return http.build();
}
- LogoutController
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Controller
public class logoutController {
@GetMapping("/logout")
public String logout(HttpServletRequest request, HttpServletResponse response) throws Exception {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if(authentication != null) {
new SecurityContextLogoutHandler().logout(request, response, authentication);
}
return "redirect:/";
}
}
- 로그아웃 컨트롤러에서 “/logout” url에 대해 요청을 받는다
- SecurityContextLogoutHandler() 를 통해 로그아웃 진행
오류 발생
- mustache에서 csrf 토큰 변수 오류 발생시 아래 구문을 변수 설정 파일에 추가
- application.properties
1
spring.mustache.servlet.expose-request-attributes=true
API 서버의 경우
- 앱에서 사용하는 API 서버의 경우 보통 세션을 STATELESS로 관리하기 때문에 스프링 시큐리티의 csrf를 enable 설정하지 않아도 된다
- 예) JWT