[ 최주호 JWT와 JUnit #8 ] - JWT (3) : JwtAuthorizationFilter 등록

정동욱·2023년 6월 22일
post-thumbnail

이번 글에서는 사용자의 권한을 검증하는 필터를 만들고 적용해보겠습니다.

이전 글에서 만들었던 JwtAuthenticationFilter 인증 필터는 로그인 시에만 작동하는 필터였습니다. 그에 반해 이번에 만들 JwtAuthorizationFilter 인가 필터는 매 요청마다 동작할 필터가 되겠습니다. 이 필터는 BasicAuthenticationFilter 필터를 상속합니다.

doFilterInternal() 매서드를 오버라이딩해 사용합니다.

  1. 요청에 토큰이 담긴 여부를 확인합니다.
  2. 토큰이 있으면, "Bearer"를 "" 빈 문자열로 변환해 검증합니다.
  3. verify() 매서드를 호출해 CustomUserDetails 객체를 반환합니다.
  4. 반환된 CustomUserDetails 객체로 Authentication 객체를 생성합니다.
  5. 생성된 Authentication 객체를 시큐리티 컨텍스트에 저장합니다.
  6. chain.doFilter()를 통해 다음 필터를 실행시킵니다.

그러니까 이 필터는 매 요청마다 동작해서 요청에 토큰이 있는지, 있다면 토큰을 검증하고 검증 후 Authentication 객체를 생성해 시큐리티 컨텍스트에 넣는 겁니다.

Authentication 객체를 시큐리티 컨텍스트에 넣는 이유는 인가 때문인데요, 무슨 말이냐면 우리는 세션 STATELESS 정책을 사용하기 때문에 이 사용자의 정보를 어디에도 저장하지 않습니다. 그래서 매 요청마다 토큰을 가져와 검증을 하면서, 이 때 토큰 검증을 통해 생성한 Authentication 객체를 시큐리티 컨텍스트에 저장해 여기서 사용자의 권한 등의 정보를 가져오는 겁니다. 만약 이렇게 하지 않는다면, 서버 측에서는 사용자의 정보에 대해 알 수 없게 되는 거죠. 그리고 이는 우리가 토큰을 생성하는 코드에 claim으로 id와 role을 넣어주었기 때문입니다.

그리고 이제 만든 인가 필터를 시큐리티에 등록해볼텐데요, 이전과 마찬가지의 방법입니다.

그리고 이전에 만든 JwtAuthenticationFilter 인증 필터에 약간의 리팩토링이 필요합니다. 로그인 인증 성공/실패 시 아래의 코드가 동작하도록 수정했습니다.

이전 글에서 봤던대로 attemptAuthentication() 매서드로 로그인을 가로채는데요, 성공 시에는 자동으로 successfulAuthentication() 매서드가 실행되고, 실패 시에는 자동으로 unsuccessfulAuthentication() 매서드가 실행됩니다.

바뀐 부분은 로그인 실패 시입니다. unsuccessfulAuthentication() 매서드가 실행되는 이유는 attemptAuthentication() 매서드의 마지막 catch 부분을 보면 InternalAuthenticationServiceException 예외를 던지는데요, 이 예외는 AuthenticationException 예외를 상속한 예외입니다. 이 예외를 unsuccessfulAuthentication() 매서드가 받아서 처리하는 것이죠. 그리고 CustomResponseUtil.fail() 매서드가 실행되는데, CustomResponseUtil도 재사용성을 위해 약간의 수정이 있었습니다.

인가 필터를 만들고 시큐리티에 적용해봤는데요, 다음 글에서는 지난 내용들을 이론적으로 정리해보겠습니다.

profile
거인의 어깨 위에서 탭댄스를

0개의 댓글