Argument Resolver란?
업데이트:
Argument Resolver란?
Argument Resolver는 컨트롤러 메서드의 파라미터 값들을 결정하고 바인딩하는 역할을 합니다. 스프링에서는 다양한 Argument Resolver를 제공하고 있습니다.
Argument Resolver의 종류
@GetMapping
public void get(HttpServletRequest req, @PathVariable long id) {}
@PostMapping
public void post(@RequestBody Body body) {}
- HttpServletRequest, @RequestParam, @RequestBody, Model 등
동작 방식
- 요청이 들어오면 DispatcherServlet이 적절한 컨트롤러 메서드를 찾습니다.
public interface HandlerMethodArgumentResolver {
boolean supportsParameter(MethodParameter parameter);
Object resolveArgument(
MethodParameter parameter,
@Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
@Nullable WebDataBinderFactory binderFactory
) throws Exception;
}
- supportsParameter() 메서드를 통해 해당 Argument Resolver가 지원하는 파라미터인지 확인합니다.
- resolveArgument() 메서드를 통해 파라미터 값을 결정하고 바인딩합니다.
Custom Argument Resolver 만들기
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Auth {
Role value() default Role.USER;
}
@Auth 어노테이션을 만들어서 커스텀 Argument Resolver를 만들어보겠습니다.
@Sl4j
@Component
@RequiredArgsConstructor
public class AuthArgumentResolver implements HandlerMethodArgumentResolver {
private final AuthService authService;
private final MemberRepository memberRepo;
@Override
public boolean supportsParameter(MethodParameter parameter) {
boolean hasAuthAnnotation =
parameter.hasParameterAnnotation(Auth.class);
boolean hasMemberType =
Member.class.isAssignableFrom(parameter.getParameterType());
log.debug("hasAuthAnnotation = {}, hasMemberType = {}", hasAuthAnnotation, hasMemberType);
return hasAuthAnnotation && hasMemberType;
}
@Nullable
@Override
public Object resolveArgument(
MethodParameter parameter,
@Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
@Nullable WebDataBinderFactory binderFactory
) {
// token 얻기
String token = webRequest.getHeader("Authorization");
if (!StringUtils.hasText(token)) {
throw new InvalidTokenException("'token' must not be empty");
}
// Auth 어노테이션의 role 얻기
Auth authAnnotation = parameter.getParameterAnnotation(Auth.class);
if (authAnnotation == null) {
throw new NullPointerException("'Auth annotation' must not be null");
}
Role role = authAnnotation.value();
// 토큰 검증 받기
TokenInfo tokenInfo = authService.verifyToken(token);
// member 조회
Member member = memberRepo.findByUid(tokenInfo.getUid())
.orElseThrow(() -> new InvalidTokenException("잘못된 토큰입니다"));
// role 권한 체크
if (member.getRole().getCode() < role.getCode()) {
throw new InvalidAuthException("권한이 없습니다");
}
return member;
}
}
- supportsParameter() 메서드는 Auth 어노테이션을 가지고 있으면서 Member 타입일 경우에만 true를 리턴한다.
- resolveArgument() 메서드는 요청에서 Authorization 토큰을 찾고, 파라미터에서 Role을 찾아 토큰 검증, member 조회, role 권한을 체크하고 조회한 member를 리턴한다.
- 권한과 토큰을 검증하게 되면서 컨트롤러 메서드에서 Auth 어노테이션을 사용하게 되면서 권한을 체크할 수 있게 된다.
참고사이트
https://velog.io/@hoho4190/Spring-Boot-Custom-ArgumentResolver
댓글남기기