ArgumentResolver
ArgumentResolver 에 관한 설명은 이 글을 참고한다.
기존 Interceptor 를 사용하는 방식도 괜찮지만 이번엔 ArgumentResolver 를 사용해보자.
커스텀 애노테이션 @Login 을 만들고 이 애노테이션이 붙은 메서드만 인증 로직을 적용할 것이다.
PostController
커스텀 애노테이션 @Login 이 붙은 컨트롤러를 만든다. 이 컨트롤러는 userSession 의 hello 필드의 값을 반환한다.
@GetMapping("/hello")
public String hello(@Login UserSession userSession) {
return userSession.getHello();
}
Login
커스텀 애노테이션을 만드는법은 생각보다 간단하다.
아래처럼 설정만하면 된다.
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Login {
}
ㄴ @Target(ElementType.PARAMETER)
우리가 만들 커스텀 애노테이션이 동작할 범위를 정한다.
파라미터에만 사용할 수 있도록 설정한다.
ㄴ @Retention(RetentionPolicy.RUNTIME)
우리가 만들 커스텀 애노테이션의 라이프 사이클을 정한다.
리플렉션 등을 활용할 수 있도록 런타임까지 애노테이션 정보가 남아있도록 설정한다.
UserSession
@Getter
public class UserSession {
private final String hello;
public UserSession(String hello) {
this.hello = hello;
}
}
AuthResolver
@Login 애노테이션이 달려있는지 확인하고 달려있다면 인증을 진행하는 ArgumentResolver 를 만든다.
public class AuthResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(Login.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
String authorization = webRequest.getHeader("Authorization");
if (authorization == null || authorization.isBlank()) {
throw new UnauthorizedException();
}
return new UserSession("Hello World");
}
}
1. supportsParameter()
ㄴhasParameterAnnotation()
해당 애노테이션이 달려있는지 확인하고 달려있을 시 resolveArgument() 메서드를 실행한다.
여기서는 @Login 을 체크한다.
2. resolveArgument()
우선은 간단하게 Authorization 헤더를 갖고있는지, 빈값이 아닌지만 체크한다.
갖고 있는 경우 hello 필드에 "Hello World" 값을 갖는 UserSession 객체를 만든다.
WebMvcConfig
AuthResolver 를 사용하기 위해 WebMvcConfig 에 추가한다.
기존의 Interceptor 를 사용하던 방식은 당분간 사용하지 않을것이므로 WebMvcConfig 에서 주석처리한다.
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
// @Override
// public void addInterceptors(InterceptorRegistry registry) {
// registry.addInterceptor(new AuthInterceptor())
// .excludePathPatterns("/error", "/favicon.ico");
// }
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new AuthResolver());
}
}
ㄴaddArgumentResolvers
위 메서드를 오버라이드 해서 우리가 만든 AuthResolver 를 추가한다.
PostControllerTest
Authorization 헤더를 추가하면 Hello World 를 출력하는 테스트를 작성한다.
@DisplayName("/hello 요청시 Hello World 를 출력한다.")
@Test
void hello() throws Exception {
mockMvc.perform(
MockMvcRequestBuilders.get("/hello")
.header("Authorization","midcon")
)
.andExpect(status().isOk())
.andExpect(content().string("Hello World"))
.andDo(print());
}
테스트는 성공하고 우리가 의도한대로 동작한다.
만약 헤더값을 빼고 테스트를 돌리면 아래와 같이 예외가 터지며 인증이 필요하다는 메시지를 반환할것이다.
'API 만들어 보기 > 게시판 API' 카테고리의 다른 글
[API 인증] DB를 통한 토큰 발급 및 검증 2 (0) | 2023.10.02 |
---|---|
[API 인증] DB를 통한 토큰 발급 및 검증 1 (0) | 2023.10.01 |
[API 인증] Interceptor 사용해보기 (0) | 2023.09.29 |
[API 인증] 가장 기본적인 요청 인증값 확인 (0) | 2023.09.28 |
[Spring REST Docs] 기본설정 (0) | 2023.09.26 |