Spring
[Spring Security] HandlerMethodArgumentResolver로 Authentication에서 Principal 정보 가져오기
jhkimmm
2022. 4. 14. 01:05
Spring Security로 JWT 토큰을 사용하면 Authentication 정보를 메서드의 파라미터로 받아올 수 있습니다.
다만 매번 Authentication에서 Principal 정보를 꺼내쓰는 코드를 작성하면 코드의 중복이 심하므로 HandlerMethodArgument를 이용해서 Principal을 바로 메서드의 파라미터로 받아오는 방법을 알아보겠습니다.
0. HandlerMethodArgumentResolver의 구성요소
HandlerArgumentResolver 인터페이스는 두 개의 메서드를 구현해줘야합니다.
boolean supportsParameter(MethodParameter parameter);
Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;
supportParameter는 해당 클래스가 파라미터로써 사용될 수 있는지 체크하는 메서드이고,
resolveArgument에서 실제 주어진 request로 부터 메서드의 파라미터를 Resolve 하게 됩니다.
1. HandlerMethodArgumentResolver구현하기
저의 경우에는 Filter 단에서 Authentication의 Principal에 User객체를 넣어주었으므로
Authentication의 Principal을 바로 리턴하였습니다.
@Component
public class AuthenticationArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
//UserDto 객체를 파라미터로 받을 수 있도록 허용함
return UserDto.class.isAssignableFrom(parameter.getParameterType());
}
@Override
public Object resolveArgument(
MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory
) throws Exception {
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if(authentication == null){
throw new RuntimeException;
}
return authentication.getPrincipal();
}
}
2. WebMvcConfigurer에 Resolver 등록하기
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new AuthenticationArgumentResolver());
}
}
스프링 부트에서 Resolver를 인식할 수 있도록 등록해줍니다.
3. 사용법
<Before>
@PostMapping
public ResponseEntity<Void> createNoteBook(
@Valid @RequestBody NoteBookDto noteBookDto,
Authentication authentication
){
User user = (User) authentication.getPrincipal();
//서비스 로직 ..
return ResponseEntity.ok().build();
}
원래는 위처럼 일일히 Authentication을 User 객체로 변환하는 코드를 추가해줘야 했지만,
<After>
@PostMapping
public ResponseEntity<Void> createNoteBook(
@Valid @RequestBody NoteBookDto noteBookDto,
UserDto userDto
){
//서비스 로직 ..
return ResponseEntity.ok().build();
}
HandlerMethodArgumentResolver를 만들고나면 컨트롤러에서 UserDto 객체를 파라미터로 바로 받아서 사용할 수 있습니다.