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 객체를 파라미터로 바로 받아서 사용할 수 있습니다.