-
AI 검증 비즈니스 프로젝트 - 로그인 관련 트러블 슈팅회고 2024. 8. 28. 23:16
시작하며
더보기Spring Security와 JWT를 사용하여 회원가입, 로그인을 구현하고자 했다. 회원가입을 완료하고, 로그인을 했더니 403 FORBIDDEN에러가 발생했다. 확인 결과 UsernamePasswordAuthenticationFilter를 상속해서 커스텀한 Filter를 호출하지 못하고 있었다. 왜 안되는지 몇 시간 동안 씨름을 하다 결국 내부 코드를 까서 원인을 찾았다.
어떤 문제가 있었고 어떻게 찾았는지, 그리고 어떻게 해결했는지 정리해 보겠다.
1. 전체적인 흐름 정리
먼저 jwt를 사용할 때의 전체적인 흐름에 대해서 먼저 정리해 보겠다.
1) SpringSecurity의존성을 추가하게 되면 기존 톰켓의 Servlet 컨테이너의 필터 체인에 DelegatingFilter를 등록하게 된다. 이름에서 알 수 있듯이 DelegatingFilter는 모든 요청을 가로채서 SecurityFilterChain에 넘긴다.
2) jwt를 사용하려면 기존 security의 기본 동작 방식을 disabled 시켜줘야 한다.


3) formLogin을 disabled로 해주고, 세션 옵션을 stateless로 바꿔주면 SpringSecurityFilter의 UsernamePasswordAuthenticationFilter가 동작을 하지 않게 된다. 이 필터는 로그인 요청을 처리하는 필터인데, 인증 정보를 검증하여, 인증 과정을 처리한다. 이 필터가 동작을 하지 않으므로, 강제로 커스텀해서 JWT인증 시 작동하도록 설정을 해줘야 한다!!
4) 따라서 UsernamePasswordAuthenticationFilter를 상속받아서 커스텀을 하고, 추가로 발급된 토큰에 대해서 인증, 인가 처리를 하는 Filter도 커스텀하여, SecurityConfig파일에 Filter를 추가했다.



5) 로그인 요청에 대해 테스트를 하기 위해, 회원가입부터 진행하고 로그인을 진행하였다.

6) 전에 이미 완료했던 회원가입은 잘 진행됐고 로그인 요청을 하였는데, 403 Forbidden에러가 발생했다.

2. 트러블 슈팅 과정
1) 코드의 논리 확인
우선은 어디서 문제가 생겼는지 찾아야 했다... JWT를 처음 사용하는 것이어서 최대한 흐름이 어떻게 되는지 붙잡으면서 코드를 작성했다. 많은 자료조사도 했고, 공식 문서도 확인하면서 어느 정도 납득이 되면 스텝을 밟았다.
그럼에도 불구하고 예외가 터지니 내가 이해했던 부분에 대해 신뢰도도 내려가고, 처음부터 다시 확인할 수밖에 없었다. 의존성 주입이 잘 됐는지부터, 전체적인 흐름에 대해 다시 검토를 하였지만, 로직에는 문제가 없는 것 같았다.
2) 로그 찍기
로직에는 문제가 없어서 더 문제였다. 그래서 찍을 수 있는 모든 곳에 로그를 찍기 시작했다. 그 결과 내가 커스텀해서 등록한 Filter 중 UnernamePasswordAuthenticationFilter를 상속받아 커스텀 한 필터가 호출되지 않는다는 것을 알아냈다.

부끄러운 로그의 흔적인데,, 해당 로그가 찍히지 않는 것을 발견했다. 그렇지만, 로직도 괜찮았고 해당 필터도 당연히 등록을 해줬기 때문에 몇 시간 동안 뭐가 문제인지 찾지를 못하였다...
3) security 디버그 모드
@EnableWebSecurity의 debug옵션을 true로 바꾸고 애플리케이션을 실행하니 여러 정보들이 나왔다. 정보들 중에 적용된 filter chain들이 있었는데, 호출이 안된다고 생각했던, JwtAuthentiationFilter가 등록되어 있었다..!!


4) 인텔리제이 디버거
따라서 AuthenticationFilter에 문제가 있는 것 같으니, 바로 위 필터인 JwtAuthorizationFilter에 브레이크 포인트를 걸고 디버깅을 진행했다.

뭔가 보이는 것 같으면서도 문제점을 찾지 못하였다...

5) 직접 코드 내부 들여다보기
그래도 위에서 말한 필터 주변에서 문제가 있는 것 같으니, 상속받은 필터의 코드 내부를 들여다보기로 하였다. UsernamePasswordAuthenticationFilter인데 이미 글이 너무 길어졌으니, 다음 글에서 트러블 슈팅 과정을 마무리하겠다..!
마치며
더보기글을 쓰며 전체적인 흐름에 대해 다시 정리된 기분이다. JWT를 통해 로그인, 회원가입을 구현해 보았다면, 위 글을 읽고 어디서 문제가 있었는지 이미 찾았을 수도 있다. 다음 글에서 마저 정리해 보도록 하겠다.
그리고 디버깅의 중요성에 대해서 다시 한번 알게 되었다. 뭔가 모르겠다 싶으면, 디버거를 사용해서 디버깅도 해보고, 내부 코드를 보는 것에 대해 두려워하지 말아야겠다. 엄청 오랜만에 본 것 같은데, 너무 재밌었다.
'회고' 카테고리의 다른 글
메일 발송 원리 (3) 2024.10.12 토큰 유효성 검사 관련 리팩토링 (0) 2024.10.07 AI 검증 비즈니스 프로젝트 2일차 회고(1일차 고민 해결) (0) 2024.08.23 AI 검증 비즈니스 프로젝트 1일차 회고(API, ERD, 테이블, 인프라 명세서 작성) (0) 2024.08.22