카카오 로그인 구현하기(4) - 커스텀 어노테이션을 통해 사용자 정보, Token 정보 가져오기

minchan·2024년 8월 15일

SpringBoot

목록 보기
9/14

1. 커스텀 어노테이션 도입

모든 API에서 동일한 코드가 반복되는걸 막기 위해, 커스텀 어노테이션을 만들어서 파라미터에서 사용자 정보 또는 토큰 정보를 가져올 수 있도록 하는 방법

2. Argument Resolver

2.1 Argument Resolver란?

Argument ResolverAPI 엔드포인트로 인입된 데이터를 가공 및 바인딩 할 때 사용하는 객체

  • http body 또는 url parameter로 넘어오는 데이터들은, @ReqeustBody@RequestParam 등으로 바인딩이 가능하지만, http header, 쿠키, 세션 등으로 전달되는 데이터인 경우에는 Argument Resolver를 이용할 수 있음.

💡 Argument Resolver는 대표적으로 세션에서 로그인한 사용자의 정보를 얻거나, 헤더로 전달되는 인증 정보에서 토큰의 정보 및 사용자의 정보를 얻을 때 사용

2.2 Argument Resolver 호출 시기

Argument Resolver가 호출되는 시기는 handler adapter를 찾은 이후 Argument Resolver가 처리되고, 이후 Handler를 실행

💡 즉, 컨트롤러 method → Argument Resolver 처리 → 컨트롤러 method 실행

3. 토큰 추출 커스텀 어노테이션 만들기

3.1 어노테이션 선언

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface GetToken {
}

@Target

이름설명
PACKAGE패키지 선언 시
TYPE타입(클래스, 인터페이스, enum) 선언 시
CONSTUCTOR생성자 선언 시
FIELDenum 상수를 포함한 멤버변수 선언 시
METHOD메소드 선언시
ANNOTATION_TYPE어노테이션 타입 선언 시
LOCAL_VARIABLE지역변수 선언 시
PARAMETER파라미터 선언 시
TYPE_PARAMETER파라미터 타입 선언 시

@Retention

이름설명
RUNTIME컴파일 이후에도 참조 가능
CLASS클래스를 참조할 때 까지 유효
SOURCE컴파일 이후 어노테이션 정보 소멸

3.2 Argument Resolver 구현

@Slf4j
@Component
@RequiredArgsConstructor
public class GetTokenArgumentResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        boolean isString = parameter.getParameterType().equals(String.class);
        boolean isGetToken = parameter.hasParameterAnnotation(GetToken.class);

        return isString && isGetToken;
    }

    @Override
    public Object resolveArgument(
            MethodParameter parameter,
            ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest,
            WebDataBinderFactory binderFactory) {

        String refreshToken = webRequest.getHeader("Authorization");
        if (refreshToken == null || refreshToken.isEmpty()) {
            throw new GlobalException(GlobalErrorCode._UNAUTHORIZED);
        }
        if (!refreshToken.startsWith("Bearer ")) {
            throw new GlobalException(GlobalErrorCode.AUTH_INVALID_TOKEN);
        }

        return refreshToken.substring(7);
    }
}
  • supportsParameter() 컨트롤러의 method에 존재하는 파라미터들에 대해서 검사하여, 적용 여부를 판단
    1. GetToken.class (커스텀 어노테이션) 존재 여부
    2. parameter 타입이 String.class에 해당 여부
  • resloveArgument() supportsParameter() 가 true값을 return하면 실행되는 메서드 파라미터에 전달할 객체를 return

3.3 Resolver 추가

구현한 Resolver를 등록해줘야 동작을 함

@RequiredArgsConstructor
@Configuration
public class WebConfig implements WebMvcConfigurer {

    private final GetTokenArgumentResolver getTokenArgumentResolver;

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(getTokenArgumentResolver);
    }
}

WebMvcConfigurer의 구현체를 만들고 addArgumentResolvers 메서드를 오버라이딩 하여 List에 구현체를 추가

3.4 사용 방식

@Operation(summary = "토큰 재발급", description = "access 토큰이 만료된 경우 refresh 토큰을 통해 토큰을 재발급 합니다.")
@GetMapping("/kakao/reissue")
public ApiResponse<AuthResponseDTO.AuthToken> reissueToken(@GetToken String refreshToken) {
    return ApiResponse.onSuccess("토큰 재발급 성공", authService.reissueToken(refreshToken));
}

컨트롤러 method에 파라미터에 적용

resolver가 인증 헤더에서 refresh Token을 추출하여 반환

참고

[JWT] 세션 의존성 제거하기 - 커스텀 어노테이션 활용

profile
chanmin

0개의 댓글