λκΈ°λΆμ λμμΌλ‘ μ²μμΌλ‘ Interceptor λ₯Ό μ μ©ν΄λ³΄μμ λμ€μ μ¬μ©ν μΌμ΄ μμ λ μ°Ύμλ³΄λ €κ³ μ¨λ΄ λλ€!
μλμ κ°μ Controller μ Header μμ μΈμ¦μ μν κ°μ λ°μμΌμ§λ§ μ κ·Όν μ μλλ‘ μ€μ νκ² μ΅λλ€!
@RestController
@RequestMapping("/orders")
@RequiredArgsConstructor
public class OrdersController {
private final OrdersService ordersService;
@Auth(type = ApiServiceType.HOMEPAGE)
@GetMapping
public ResponseEntity<List<OrdersDto>> getOrders(
@RequestParam(required = false) String searchKeyword,
@AuthAccount Long accountId
) {
List<OrdersDto> response = ordersService.getAccessibleOrders(accountId,
searchKeyword);
return new ResponseEntity<>(response, HttpStatus.OK);
}
}
보ν΅μ μλμ κ°μ΄ κ²½λ‘λ₯Ό μΆκ°ν΄μ interceptorλ₯Ό κ±Έμ΄μ£Όλλ° μ»€μ€ν μ΄λ Έν μ΄μ μΌλ‘ νμ©ν μλ μλλΌκ΅¬μ! ( μ λ§ μκ°λ λͺ»νλ€,,)
registry.addInterceptor(interceptor)
.addPathPatterns("/**")
.excludePathPatterns("/main");
https://www.baeldung.com/java-custom-annotation
μλμ κ°μ΄ 컀μ€ν μ΄λ Έν μ΄μ μ λ§λ€μ΄ μ€λλ€.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Auth {
ApiServiceType type();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface AuthAccount {
}
@Retention μ λ§κ·Έλλ‘ μ΄ μ΄λ Έν μ΄μ μ΄ μΈμ κΉμ§ μ μ§ν μ§λ₯Ό μ ν©λλ€.
- RUNTIME λ°νμ κΉμ§ μ μ§νλ€. = μ¬μ€μ μ¬λΌμ§μ§ μλλ€. (λ©λͺ¨λ¦¬μ κ°μ΄ μ¬λΌκ°)
- SOURCE μμ€μ½λ κΉμ§ μ μ§νλ€. = .java μμ€κΉμ§ μ μ§νλ€ (μ»΄νμΌλμ΄ ν΄λμ€ νμΌμ΄ λλ©΄ μ¬λΌμ§λ€)
- CLASS ν΄λμ€νμΌ κΉμ§ μ μ§νλ€. = μ»΄νμΌν class νμΌκΉμ§ μ μ§νλ€ (λ©λͺ¨λ¦¬λ‘ μ½μ΄μ€λ©΄ μ¬λΌμ§)
μ¬μ€ μ΄λ€μμΌλ‘ μ¬μ©ν΄μΌν μ§ κ°μ΄ μμ¨λ€ ... λͺκ°μ§ μ°Ύμλ³Έκ² μλ€λ©΄
μ€νλ§μ λλΆλΆμ μ΄λ Έν μ΄μ μ RUNTIME μΌλ‘ λμ΄μλ€κ³ νλ€.
μλνλ©΄ μ€νμ€μΈ μνμμ μ€νλ§ μ»΄ν¬λνΈ μ€μΊμ΄ μ€μΊμ ν΄μΌνκΈ° λλ¬Έμ!
@getter κ°μ κ²½μ°λ λ‘¬λ³΅μ΄ μ½λλ₯Ό μμ±ν΄μ£Όλ κ±°λκΉ λ°μ΄νΈμ½λμ μμ€κ° λ€μ΄κ° νμκ° μμ΄μ SOURCE λ‘ λμ΄μλ€.
Maven μ΄λ Gradle μμ λ°μ λΌμ΄λΈλ¬λ¦¬ λ€μ class νμΌλ‘ μκΈ° λλ¬Έμ μ΄λ Έν μ΄μ μ μ 보λ₯Ό μ 보λ₯Ό μ‘°ννκΈ° μν΄ CLASS λ‘ λμ΄μλ€.
@Target μ μλ° μ»΄νμΌλ¬κ° annotationμ΄ μ΄λμ μ μ©λ μ§ κ²°μ νκΈ° μν΄ μ¬μ©ν©λλ€!
ElementType.PACKAGE : ν¨ν€μ§ μ μΈ
ElementType.TYPE : νμ
μ μΈ
ElementType.ANNOTATION_TYPE : μ΄λ
Έν
μ΄μ
νμ
μ μΈ
ElementType.CONSTRUCTOR : μμ±μ μ μΈ
ElementType.FIELD : λ©€λ² λ³μ μ μΈ
ElementType.LOCAL_VARIABLE : μ§μ λ³μ μ μΈ
ElementType.METHOD : λ©μλ μ μΈ
ElementType.PARAMETER : μ λ¬μΈμ μ μΈ
ElementType.TYPE_PARAMETER : μ λ¬μΈμ νμ
μ μΈ
ElementType.TYPE_USE : νμ
μ μΈ
곡μλ¬Έμ! μμ 보면 array λ‘ μ¬λ¬κ°λ₯Ό μ¬μ©ν μλ μλ€μ!
https://docs.oracle.com/javase/8/docs/api/java/lang/annotation/ElementType.html
μ§κΈμ METHOD , PARAMETER λ₯Ό μ΄λ»κ² μ¬μ©νλμ§ λ³΄κ² μ΅λλ€!
μ²μ 컨νΈλ‘€λ¬μμ μλμ κ°μ΄ μ°μΈκ²μ 컀νΈν μ΄λ Έν μ΄μ μΈ @Auth μ ElmentType μ΄ METHD μΈλ° λ©μλλ₯Ό μ μΈν μ μλ€λ κ²λλ€! κ·Έλμ μμ μ½λλ₯Ό νμΈν΄λ³΄μλ©΄ ApiServiceTypeμ enum μΌλ‘ λ©μλλ₯Ό μ μΈν΄λμμ΅λλ€!
@Auth(type = ApiServiceType.HOMEPAGE)
@AuthAccount λ ElemntType μ΄ parameter λ‘ μ»¨νΈλ‘€λ¬μμ νλΌλ―Έν°λ‘ λ°κ³ μλκ±Έ νμΈν μ μμ΅λλ€
본격μ μΌλ‘ Interceptor μ μ©μ ν΄λ³΄κ² μ΅λλ€!
Interceptor μ μ©ν class λ₯Ό λ§λ€μ΄μ€λλ€!
@Component
@RequiredArgsConstructor
public class Interceptor implements HandlerInterceptor {
private final AuthService authService;
// νΈμΆν Controller κ° μ€νλκΈ°μ μ€νλλ λ©μλ (μ¬μ μ μ΄)
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
HandlerMethod handlerMethod = (HandlerMethod) handler;
// MethodAnnotation μΌλ‘ 컨νΈλ‘€λ¬μ Auth.class λ‘ μ§μ ν κ°μ κ°μ§κ³ μ¨λ€
// νμ¬ Api.ServiceType.HOMPAGE λ‘ μ§μ νμ(Controller class νμΈ)
Auth auth = handlerMethod.getMethodAnnotation(Auth.class);
if (auth == null) {
return true;
}
AuthCheck authCheck = AuthCheck.builder()
.authId(request.getHeader("auth_id"))
.authSecret(request.getHeader("auth_secret"))
// hadlerMethod λ‘ κ°μ§κ³ μ¨ auth
.apiServiceType(auth.type())
.build();
// μΈμ¦ λ‘μ§μμ μ€ν¨
if (!authService.authentication(authCehck)) {
throw new InvalidClientException();
}
// return μ΄ true μΌκ²½μ° ν΄λΉ Controllerλ‘ λμ΄κ°
return true;
}
}
implements HandlerInterceptor
μ¬κΈ°μ HandlerInterceptor λ₯Ό implemnts λ°μμ Interverptor λ₯Ό μ μ©νλ©΄ λ©λλ€. 곡μλ¬Έμμμ μλμ κ°μ΄ μ€λͺ λμ΄μμ΅λλ€!
Spring interceptor λ HandlerInterceptor λ₯Ό μ΄μ©νμ¬ κ΅¬ννκ±°λ HandlerInterceptorAdapter λ₯Ό μ΄μ©ν΄ νμ₯ν μ μλ€κ³ λμμλ€μ!
λ€μ λ§ν΄μ μΈν°νμ΄μ€λ₯Ό ꡬννκ±°λ μΆμν΄λμ€λ₯Ό μ€λ²λΌμ΄λ©μ ν΅ν΄μ μμ λ§μ μΈν°μ ν°λ₯Ό λ§λλκ±°λ€μ!
HandlerMethod handlerMethod = (HandlerMethod) handler;
μ΄ λΆλΆ μμ handler λ νμ¬ μ€ννλ €λ λ©μλ μ체λ₯Ό μλ―Έν©λλ€, νμ¬ μ€νλλ 컨νΈλ‘€λ¬λ₯Ό νμ νλ μμ μ΄ κ°λ₯νμ£ !
κ·Έλμ handlerMethod.get μ ν΅ν΄ νμ¬ μ€νν 컨νΈλ‘€λ¬μ Auth.class κ°μ κ°μ§κ³ μ€κ±°λΌ~ μ λλ€! λ§μ½ Auth.class λ₯Ό λΆμ΄μ§ μμ 컨νΈλ‘€λ¬μ΄λ©΄ interceptorλ₯Ό κ±°μ³κ° νμκ° μμΌλ true λ₯Ό λ°νν΄μ Controller κ° μ€νλκ² ν©λλ€
μ΄μ HandlerMethodArgumentResolver κ° μ΄λ»κ² μ°μ΄λμ§ νμΈν΄λ΄ μλ€
μ£Όμ΄μ§ μμ²μ μ²λ¦¬ν λ, λ©μλ νλΌλ―Έν°λ₯Ό μΈμκ°λ€μ μ£Όμ ν΄μ£Όλ μΈν°νμ΄μ€ μ λλ€!
μΈμ¦μ νμν parameter μ΄ μ€λ³΅μΌλ‘ λ°μλ μ μκΈ° λλ¬Έμ 곡ν΅μΌλ‘ μ λ ₯λλ μμ λ€μ νλ²μ μ²λ¦¬νκ³ μΆμ λ μ¬μ©ν©λλ€!
@Component
public class ArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter methodParameter) {
return methodParameter.hasParameterAnnotation(AuthAccount.class);
}
@Override
public Object resolveArgument(MethodParameter methodParameter,
ModelAndViewContainer modelAndViewContainer, NativeWebRequest request,
WebDataBinderFactory webDataBinderFactory) throws Exception {
String accountId = request.getHeader("accountId");
return crypto.toDecryptAsLong(accountId);
}
}
supportsParameter μ΄λ€ νλΌλ―Έν°μ λν΄ μμ μ ν κ±΄μ§ μ μ νλ λ©μλ μ λλ€.
μ ν¬λ 컀μ€ν μ΄λ Έν μ΄μ μΈ @AuthAccount λ₯Ό μ¬μ© νμΌλ hsParameterAnnotaion μ ν΅ν΄ νμΈν©λλ€.
λ§μ½ 컀μ€ν μ΄λ Έν μ΄μ μΈ μλ νλΌλ―Έν°λ‘ κ°μ²΄ (Dto) λ‘ μ¬μ©νκ³ μΆλ€λ©΄ μλμ κ°μ΄ μ¬μ©ν©λλ€. νμ§λ§ orderDto λ₯Ό νλΌλ―Έν°λ‘ λ°κ³ μλ 컨νΈλ‘€λ¬κ° λ§λ€λ©΄... κ°μ μμ μ μννλκ² μλλΌλ©΄(λ³΄ν΅ κ·Έλ κ² μ£ ..?) μ΄λμ μμ μλ κ°μ΄ νμ΄λμ¬μ§ μμν μ μμ κ±°κ°μ λΉμΆνλ€
return methodParameter.getParameterType().equals(orderDto.class);
resolveArgument λ λ°μΈλ©ν κ°μ²΄λ₯Ό μ‘°μνλ λ©μλ μ λλ€!
μ λ μ κΈ°μ AuthAccount λ‘ λ°μ accountId μ΄ μνΈνλμ΄ μκΈ° λλ¬Έμ 볡νΈν ν΄μ£Όμ΄ 리ν΄ν΄μ£Όκ³ μμ΅λλ€.
μ΄μ μ΄ μΈν°μ ν°μ 리볼λ²λ₯Ό μ¬μ©νλλ‘ λ±λ‘ν΄μ€ μ°¨λ‘μ λλ€!
@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {
private final ArgumentResolver argumentResolver;
private final Interceptor interceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(interceptor);
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolver) {
resolver.add(argumentResolver);
}
}
ν΄^^....;; νλ¦°λΆλΆμ΄ μλ€λ©΄ λκΈ λ¨κ²¨μ£ΌμΈμ!
'π WEB > Spring' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
Spring boot + JWT + RefreshToken ꡬννκΈ° (10) | 2021.01.29 |
---|---|
Spring bootμμ JSP μ¬μ©νκΈ° (0) | 2021.01.25 |
Mapper Interface? (0) | 2020.07.23 |
Spring μ΄μ 리 3.Annotation (0) | 2020.06.13 |
Spring μ΄μ 리 2.Spring 3λ μλμ리 (0) | 2020.06.06 |