본문 바로가기
PlayGround/마실가실 리팩토링

[1년 후 마실가실] Spring Security + JWT - LoginFilter

by HJ0216 2024. 10. 27.

1년 전 진행했던 마실가실 프로젝트를 🛠️리팩토링하며 정리한 내용입니다.

 

 

요즘 제 표정입니다.

 

Spring Security Exception 처리에 막혀서, 이건.. 이건.. 학습이 필요하다는 생각이 간절히 들어 요즘 Security 강의를 듣습니다..

 

근본.. Login부터 다시 돌아가보고자 합니다..

 

 

Spring Security에서 기본으로 제공하는 Form Login 방식을 사용하지 않기에 Form Login 방식에서 사용하는 Security Filter인 UsernamePasswordAuthenticationFilter을 상속받은 LoginFilter를 생성합니다.

username(id와 동일한 개념으로 생각하면 될 것 같습니다)과 password를 사용해서 로그인을 할 경우, obtainUsername()과 obtainPassword()를 사용하면 됩니다.

 

하지만, 저에겐 이전에 진행했던 코드가 있고.. 그 코드는.. username 대신 email로 DTO가 이뤄졌기에 ObjectMapper를 사용해서 JSON 객체를 DTO 클래스로 역직렬화해서 email과 password를 추출해서 UsernamePasswordAuthenticationToken를 만들어주었습니다.

 

UsernamePasswordAuthenticationFilter에서 AuthenticationManager를 사용하여 사용자의 인증 정보 검증을 수행합니다.

검증에 대한 반환값으로 Authentication을 받게 됩니다.

인증이 성공적으로 수행되면 successfulAuthentication 메서드가 호출되고 이후 JWT 생성과 같은 후속 작업을 수행합니다.
만일 인증 과정에서 문제가 발생하면 unsuccessfulAuthentication 메서드가 호출됩니다.

 

구체적인 순서를 정리하면 다음과 같습니다.

1. login API 호출 시, Security Filter인 Login Filter가 요청을 검증합니다.

2. login Filter는 AuthenticationManager를 사용하여 인증 작업을 수행합니다.

3. AuthenticationManager는 interface이기 때문에 실제로는 AuthenticationProvider가 인증 작업을 수행합니다.
4. AuthenticationProvider는 인증 작업을 수행할 때, UserDetailsService를 호출합니다.
5. UserDetailsService는 loadUserByUsername()를 통해 사용자 정보를 조회한 후, 사용자 인증 정보인 UserDetails를 반환합니다.
6. AuthenticationProvider는 반환된 UserDetails 객체와 클라이언트가 제공한 비밀번호를 비교하여 인증을 수행합니다.
7. 인증이 성공하면 사용자의 권한과 상태 정보가 담긴 새로운 Authentication 객체를 생성하여 반환합니다.
8. Authentication 반환 상태에 따라 successfulAuthentication 메서드를 호출하거나, 인증 실패 시 unsuccessfulAuthentication 메서드를 호출합니다.

  * 인증이 실패하면 AuthenticationProvider가 적절한 예외를 발생시키고, 이 예외는 AuthenticationManager에 의해 잡혀서 unsuccessfulAuthentication 메서드가 호출됩니다.

 

 

+ 중간에 만난 소소한 오류들

1. SecurityConfig에서 로그인 필터 적용 시, 경로가 단순히 /login이 아니라면 setFilterProcessesUrl를 설정해줘야 한다.

2. addFilterAt()은 2번째 인자의 필터 대신 첫번째 인자의 필터를 쓴다는 뜻이다.

3. BCryptPasswordEncoder를 사용하여 암호화한 경우, DB 상 password값이 BCryptPasswordEncoder 형식이 아니라면 오류가 발생한다 -> 값을 변경하고 API 실행해야 한다. 그렇지 않으면 CREDENTIALS 오류로 unsuccessfulAuthentication가 호출된다.

  * AuthenticationManager가 인증을 수행할 때, 기본적으로 Spring Security에서 제공하는 DaoAuthenticationProvider가 있으며, 사용자가 입력한 비밀번호와 UserDetails에서 가져온 암호화된 비밀번호를 비교한다. 이 과정에서 비밀번호 인코딩 방식이 자동으로 인식되어 검증이 수행된다.

 

 

 

🙋‍♀️

본 포스트는 공부 목적으로 작성하였습니다.
보시는 도중 잘못된 부분이나 개선할 부분이 있다면 댓글로 알려주시면 수정하도록 하겠습니다.

 

📑

참고 자료

https://www.devyummi.com/page?id=668d58ba680e8f4b44fc981d

 

개발자 유미 | 커뮤니티

 

www.devyummi.com

https://github.com/gdbs1107/OAuth2.0_JWT

 

GitHub - gdbs1107/OAuth2.0_JWT: OAuth2.0을 이용한 카카오,구글,네이버 소셜로그인 구현 공부

OAuth2.0을 이용한 카카오,구글,네이버 소셜로그인 구현 공부. Contribute to gdbs1107/OAuth2.0_JWT development by creating an account on GitHub.

github.com