[Spring Security] 스프링 시큐리티를 통해 로그인 시 필드 검증

olive3·2023년 11월 26일
1

스프링 시큐리티를 통해 로그인 시 필드 검증하는 법

문제

스프링 시큐리티를 통해 로그인 하는 경우 POST /login 에 대한 요청을 스프링 시큐리티가 가로채서 로그인을 진행해주기 때문에 @Valid 또는 @Validation을 통한 필드검증이 일어나지 않는다.

해결방안

CustomAuthenticationProvider을 구현해서 실제 인증 처리를 하기 전에 로그인 또는 비밀번호가 비어있는 경우 예외를 발생시키자.

구현

1. CustomAuthenticationProvider 구현

실제 인증 처리 로직은 DaoAuthenticationProvider를 그대로 사용할 것이기 때문에 AuthenticationProvider를 구현하지 않고
AuthenticaionProvider 구현체인 DaoAuthenticationProvider를 상속받아 기능을 추가하자.

실제 인증 처리를 하기 이전에 usernamepassword가 원하는 조건에 맞지 않는 경우에 예외를 발생시키자.

  • usernamenull 또는 "" 을 허용하지 않는다.
  • passwordnull 또는 "" 을 허용하지 않는다.

usernamepassword 적절한 값일 경우 인증 처리가 이루어질 것이다.

2. IllegalUsernameException과 IllegalPasswordException 커스텀 예외 만들기

처음에는 CustomAuthenticationProvider에서 IllegalArgumentException 예외를 던지려고 했으나 AuthenticationFailureHandlerAuthenticationException 만 처리하기 때문에 AuthenticationException을 상속받은 커스텀 예외를 만들었다.

3. CustomAuthenticationFailureHandler 구현

CustomAuthenticationProvider 에서 던진 IllegalUsernameException, IllegalPasswordException 예외를 CustomAuthenticationFailureHandler 에서 처리하자. SimpleUrlAuthenticationFailureHandler를 상속받아 기능을 추가했다.

4. LoginController

  • errorCode = "username" 인 경우
    bindingResult.rejectValue()loginId 필드에 대한 에러정보 추가
  • errorCode = "password" 인 경우
    bindingResult.rejectValue()password필드에 대한 에러정보 추가
  • errorCode = "object" 인 경우
    bindingResult.reject()로 객체 대한 에러정보 추가

5. login.html

@Valid 또는 @Validation 를 사용했을 때와 html은 동일하다.


스프링 시큐리티 도입 전에 @Valid + BindingResult + 타임리프 조합으로 검증하였는데 스프링 시큐리티 도입 후에 @Valid가 더이상 적용되지 않는 문제를 발견. @Valid 제거 후, BindingResult + 타임리프를 활용한 오류 표현기능을 그대로 사용하고 싶어 위와 같이 구현하였다.

다른 좋은 방법이 있다면 댓글로 알려주세요🤟🏻

1개의 댓글

comment-user-thumbnail
2023년 11월 27일

좋은 방법

답글 달기