조급하면 모래성이 될뿐

SpringSecurity 적용에 따른 CSRF처리 본문

구현 기록/SpringSecurity

SpringSecurity 적용에 따른 CSRF처리

Pawer0223 2020. 3. 12. 22:55

기존에 구축한 프로젝트에 SpringSecurity를 적용하였는데... 회원가입화면에서 2가지 기능에서 에러가 발생하였다..

 

ㅇ회원가입 화면

 

1. ID 중복체크버튼 클릭 [ AJAX를 통한 POST요청 ]

 

ID중복체크 버튼을 눌러도 아무 반응이 없었다.. F12를 눌러서 에러를 확인해보니 아래와 같았다.

2. 회원가입버튼 클릭 [ form 태그를 이용한 POST요청 ]

 

회원가입 버튼을 눌렀더니, SpringSecurity의 access-denied-handler가 작동하였다.. 

원래 access-denided-handler는 권한이 없는 사용자가 잘못된 URL접근을 제어하기위해 추가한 설정인데..

form태그에서 수행되는 action의 url은 permitall의 권한을 가지고있다.

 

즉, 이 에러도 똑같이 403에러가 발생하였다.

 

 

 

뭔일인가 싶어서 SpringSecurity 403 이라고 검색해서 찾아보니

문제의 원인은 SpringSecurity에서 CSRF공격을 방어하기위한 기능도 제공하는데, 이 방어 기법은 http메서드를 통해서 데이터를 전달할 때, CSRF토큰( 쉽게 구분 값정도..? )가 있는지 없는지 확인한다고한다.

 

그래서 SpringSecurity가 적용된 시점에서 내가 기존에 구현한 1번 중복체크, 2번 회원가입에서 403에러가 발생한 것이었다....!

 

해결 책으로는 이 CSRF토큰을 같이 전달해 주었다.

 

AJAX적용시 CSRF토큰 전달방식

 

- Ajax 요청 Header에 csrf token 정보를 포함시켜서 전송한다.

- 중복체크를 누르면 수행되는 함수에 아래코드를 추가해 주었다.

- ajaxSend는 Ajax요청을 보내기전 호출되는 메서드이다.

$(document).ajaxSend(function(e, xhr, options) {
xhr.setRequestHeader( "${_csrf.headerName}", "${_csrf.token}" );
});

 

FORM태그 전송시 CSRF토큰 전달방식

- 일반적인 경우에는 아래와같이 hiddne속성의 input태그의 value를 넘겨주면된다.

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />

그런데.. 위처럼 적용했더니 내 회원가입 form에서는 조치가 되지않았다.. ㅡ..ㅡ

 

찾아보니.. 나는 form태그에서 파일업로드기능을 수행하기위해 아래와같이 enctype을 multipart/form-data로 설정을 해주었었다..

form method="post" enctype="multipart/form-data" action="/com/userRegist.do">

위와같이 multipart/form-data로 지정된 경우에는 아래와같이 action의 url정보에 토큰 값을 같이 넘겨주면된다.. 

form method="post" enctype="multipart/form-data" action="/com/userRegist.do?${_csrf.parameterName}=${_csrf.token}">

처음엔.. 어느부분이 문제인지를 몰라서 한참 해멨다..

 

추가로 CSRF란 무엇인지, 또 SpringSecurity에서는 CSRF방어를위해 어떤 설정을 할 수 있는지 찾아보았다..

 

CSRF란?

[ 링크 ]

 

SpringSecurity CSRF 프로텍션 적용

[ 링크 ]

반응형