BugNote
UsernamePasswordAuthenticationFilter 를 상속받아 재구현 할때 조심할것
제뉴어리맨
2022. 10. 19. 23:41
상황
JWT로 권한부여와 요청에대한 검증을 하려고 구현중일때,
레퍼런스 코드를 보고 구현하고 있는데
UsernamePasswordAuthenticationFilter를 상속받아 임의의 클래스를 만들고
인증이 성공했을때 토큰만 발행하면 되기 때문에 아래의 성공시 콜백 메소드만 재정의 하고
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
FilterChain chain, Authentication authResult) throws IOException, ServletException {
//토큰 생성하여 발행 코드 필요
}
아래의 인증 구현 메소드를 굳이 따로 Overriding 할 필요가 있을까란 생각을 했다.
@SneakyThrows //예외처리를 명시적으로 해주는 애노테이션
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
//Username과 Password를 DTO 클래스로 역직렬화(Deserialization)하기 위해 ObjectMapper 인스턴스 생성
ObjectMapper objectMapper = new ObjectMapper();
//request로 들어온 Username과 Password를 LoginDto 객체로 만듦 (역 직렬화)
LoginDto loginDto = objectMapper.readValue(request.getInputStream(), LoginDto.class);
//리턴할 Authentication 구현 객체 생성
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(loginDto.getUsername(),loginDto.getPassword());
//검증 과정 거친 뒤 인증된 Authentication 리턴
return authenticationManager.authenticate(authenticationToken);
}
단순히 AuthenticationManager에게 인증을 하라고 위임만 하기 때문이다.
그런데, 위에 메소드를 구현하지 않으면
UsernamePasswordAuthenticationFilter 를 내가 구현한 클래스로 작동하지 않으면서(이건 어찌보면 당연하다)
아래에 주석이 적힌 라인에서 AuthenticationManager가 Null일면서 에러가 발생한다.
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
if (this.postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
String username = obtainUsername(request);
username = (username != null) ? username.trim() : "";
String password = obtainPassword(request);
password = (password != null) ? password : "";
UsernamePasswordAuthenticationToken authRequest = UsernamePasswordAuthenticationToken.unauthenticated(username,
password);
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest); // 에러지점
}
상속받았음에도 재정의 하지 않아서 내가 구현한 attemptAuthentication() 가 작동하지 않는것은 의도한것인데
왜 AuthenticationManager가 상위 클래스에서 Null인지는 모르겠다..
더 알아봐야할듯하다..
결론
UsernamePasswordAuthenticationFilter 를 상속받아 구현한다면,
attemptAuthentication() 메소드는 꼭 구현하여야 한다.