Spring 프로젝트를 진행할 때 항상 Security와 Jwt로 사용자 인증을 해왔다.
지난 프로젝트 피드백에서 클라이언트에서 서버로 보낸 토큰 정보를 @Authenticationprincipal 어노테이션을 사용해서 가져올 수 있다는 이야기를 듣고 코드를 바꿔보면서 어떻게 동작하는지 알아보았다.
MemberController.java
@RequestMapping(value = "/api/auth/member/logout", method = RequestMethod.POST)
public ResponseDto<?> logout(HttpServletRequest request) {
return memberService.logout(request);
}
원래 사용했던 방식은 controller에서 클라이언트의 request를 받아서
MemberService.java
public ResponseDto<?> logout(HttpServletRequest reqeust){
if (!tokenProvider.validateToken(reqeust.getHeader("RefreshToken"))) {
return ResponseDto.fail("INVALID_TOKEN", "Token이 유효하지 않습니다.");
}
Member member = tokenProvider.getMemberFromAuthentication();
if (null == member) {
return ResponseDto.fail("MEMBER_NOT_FOUND",
"사용자를 찾을 수 없습니다.");
}
return tokenProvider.deleteRefreshToken(member);
}
request의 headers에 담겨있는 토큰값으로 토큰의 유효성 검사를 한 후에 별도로 member 정보를 가져왔었다.
MemberController.java
@RequestMapping(value = "/api/auth/member/logout", method = RequestMethod.POST)
public ResponseDto<?> logout(@AuthenticationPrincipal UserDetailsImpl userDetails) {
return memberService.logout(userDetails);
}
@Authenticationprincipal 어노테이션을 사용하면 Security의 UserDetails라는 사용자 정의 인터페이스에서 return한 객체를 받아올 수 있다.
MemberService.java
public ResponseDto<?> logout(UserDetailsImpl userDetails){
if (null == userDetails.getMember()) {
return ResponseDto.fail("MEMBER_NOT_FOUND",
"사용자를 찾을 수 없습니다.");
}
return tokenProvider.deleteRefreshToken(userDetails.getMember());
}
Service 단에서 별도로 토큰의 유효성 검사를 할 필요없이 Security를 통해 사용자 인증을 거치기 때문에 UserDetails에서 바로 사용자 정보를 가져와서 사용할 수 있게 된다.
@AuthenticationPrincipal 어노테이션을 쓰면서 코드도 더 간결해지고 편리성도 좋아졌다.
더 자세한 Spring Security 동작 방식도 참고하면 더 재미있고 이해하기 좋을 것 같다.
@AuthenticationPrincipal 어노테이션은 어떻게 동작할까??