회원가입 이메일 기능을 구현하던 중에 발생한 오류를 해결하는 과정이다.
사실 이때쯤 되니 오기가 생기기 시작했다. 간단한 이메일 인증 서비스도 구현 못하면 앞으로의 기능들은 더욱 만들기 어려울 것 같았다. 그래도 지금까지의 401 오류가 아니라 403 오류가 발생했다는 것에 위안을 삼고 계속해서 구글링과 서치를 시작했다. 거의 4~5일 정도가 걸린 것 같았다.
📌 403 오류란...?
그렇게 구글링과 인터넷 검색을 계속하던 중...
어떤 개발 커뮤니티를 발견하게 되었다!
https://www.popit.kr/spring-security-ajax-%ED%98%B8%EC%B6%9C-%EC%8B%9C-csrf-%EA%B4%80%EB%A0%A8-403-forbidden-%EC%97%90%EB%9F%AC/
내용인 즉슨, Spring Security를 이용할 경우 Ajax의 POST 호출 시 403 Forbidden 에러가 발생하며 Security 설정에서 permitAll로 설정을 해도 계속 문제가 발생한다는 내용이었다. 이러한 문제는 CSRF 때문에 발생한다고 한다. 나의 상황과 정확히 일치했다!
📌
CSRF
란?
Cross Site Request Forgery(사이트 간 요청 위조)
의 줄임말로 웹 취약점 중 하나. 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위(데이터 수정, 삭제, 등록 등) 을 특정 웹사이트에 요청하게 하는 공격
더 자세한 내용 : https://devscb.tistory.com/123
즉, CSRF를 막기 위해 Spring Security에서 자체적으로 보안을 걸어놓은 것이다.
커뮤니티에서 제시한 해결책은 다음과 같다.
http.csrf().disable()
와 같이csrf
를 disable 하라고 하지만 이렇게 할 경우 보안에 문제가 발생할 수 있기 때문에 추천하지 않습니다.- 심플하게 Ajax 요청 Header에 csrf token 정보를 포함해서 전송하면 됩니다. 다음과 같이 HTML의
<head>태그
내에 csrf meta tag를 추가합니다.
내가 생각해도 csrf 자체를 disable 해버리는 것은 위험해보였다. 물론 지금 나의 프로젝트는 현금 거래가 이루어지고 관련 정보가 저장되는 단계는 아니지만 실제 운영하는 프로젝트라면 이 같은 설정은 보안 측면에서 상당히 위험해보였다.
그러면 두 번째 방법...Ajax 호출의 header에 csrf token을 추가하는 작업을 해야하는데.. 더 이상 Ajax 설정을 공부하기가 귀찮았다...(쓸데없는 고집)
그렇게 다른 방법을 찾아보다가 "Spring Boot CSRF AJAX 전송 방법" 이라는 아주 아주 솔깃한 제목의 블로그를 보게되었다.
(현사또님의 블로그 https://hyunsangwon93.tistory.com/28)
그리고 이를 통해 해답을 얻게 되었다!!🤗
모든 CSRF를 disable 하지 않으면서 특정 매핑 URL에서만 무시하는 방법인 것 같았다. 냅다 SecurityConfig
에 추가해보았다.
SecurityConfig.java
http.authorizeRequests() // 시큐리티 처리에 HttpServletRequest를 이용한다는 것을 의미
.mvcMatchers("/css/**", "/js/**", "/img/**").permitAll() // 모든 사용자가 인증(로그인) 없이 해당 경로에 접근할 수 있도록 설정
.mvcMatchers("/", "/members/**", "/item/**", "/images/**", "/mail/**").permitAll()
.mvcMatchers("/admin/**").hasRole("ADMIN") // /admin으로 시작하는 경로는 해당 계정이 ADMIN Role일 경우에만 접근 가능하도록 설정
.anyRequest().authenticated()
.and()
.csrf().ignoringAntMatchers("/mail/**") // csrf disable 설정
;
이제... 정말 경건하고 간절한 마음으로 실행해보자...
그렇다! 동작 화면이라는 목차가 나왔다는 것은 성공이라는 뜻!
회원가입시 이메일 인증 기능은 다음과 같이 동작한다.
먼저 회원가입 탭에 이메일을 전송받을 유효한 이메일을 입력한다.
그리고 전송 버튼을 누른다.
그러면 위와 같이 인증번호가 발송되었다는 메세지가 뜨고, (저 메세지를 보기 위해 그동안 얼마나 고군분투하였는지...🥲) 인증번호를 입력할 수 있는 input text가 생긴다.
이제 실제로 입력한 이메일의 우편함을 확인하자.
전송이 잘된 것을 볼 수 있다.
이제 입력창에 번호를 입력해보자. 그 전에 먼저 일부러 틀린 번호(123456)를 입력하면...
번호가 다르다고 하면서 경고창이 뜬다. 이제 전송된 올바른 인증번호를 입력하고 이메일 인증 버튼을 누르게되면...
"인증되었습니다." 라는 메세지가 뜨면서 회원가입을 계속할 수 있게 되었다.