본문 바로가기
KOTLIN

spring filter에서부터 커스텀 어노테이션, 객체 파라미터에 값 넣기

by fouink 2023. 9. 21.

처음 필터 단에서 내 나름대로 설계한 인증이 필요한 API EndPoint가 요청으로 들어온다면 헤더의 Authorization의 key값을 조회해서 해당 회원이 존재하는지 확인하고 회원이 존재하면 (로그인 된 상태라면) API 파라미터에 값을 채워넣어주는 로직을 코틀린 공부겸, 간단하게 만들어봤다.

 

class AuthFilter(
    val custSessionRepository: CustSessionRepository
) : OncePerRequestFilter() {
    override fun doFilterInternal(
        request: HttpServletRequest,
        response: HttpServletResponse,
        filterChain: FilterChain
    ) {

        val uri = request.requestURI

        if (!uri.startsWith("/api/ch")) {
            filterChain.doFilter(request, response)
            return
        }

        val requestSessionId = request.getHeader("Authorization")

        if (requestSessionId == null) {
            throw NoSuchElementException("로그인이 필요한 요청입니다.")
        }

        val custSession = custSessionRepository.findById(requestSessionId)
            .orElseThrow { NoSuchElementException("로그인이 필요한 요청입니다.") }

        val currentCust = CurrentCust(custSession.custId)
        request.setAttribute("currentCust", currentCust)

        filterChain.doFilter(request, response)
    }

}

 

필터에서 원하는 EndPoint인지 검사하여 적절히 다음로직으로 넘겨주고,

 

@Configuration
class AuthConfig : HandlerMethodArgumentResolver {
    override fun supportsParameter(parameter: MethodParameter): Boolean {
        return parameter.parameterType.isAssignableFrom(CurrentCust::class.java) &&
                parameter.hasParameterAnnotation(User::class.java)
    }

    override fun resolveArgument(
        parameter: MethodParameter,
        mavContainer: ModelAndViewContainer?,
        webRequest: NativeWebRequest,
        binderFactory: WebDataBinderFactory?
    ): Any? {
        return webRequest.getAttribute("currentCust", RequestAttributes.SCOPE_REQUEST)

    }
}

 

위의 로직이 실행되는데 설명을 해보자면 supportParameter의 메서드 반한 타입이 true라면 resolveArgument 메서드가 실행되고

@User 어노테이션과 CurrentCust type이 같이 붙은 파라미터에 최종 값을 return " " 에 담아 반환한다.

 

결과적으로 API 부분은 아래와 같이 사용할 수 있다.

 

@PostMapping
    fun createMall(
        @Valid @RequestBody request: MallRegisterRequestDto,
        @User user: CurrentCust
    ): ResponseEntity<Any> {

        val requestCust = custRepository.findById(user.custId)
            .orElseThrow { NoSuchElementException("") }

        val newData = Mall(
            mallName = request.mallName!!,
            mallKey = UUID.randomUUID().toString(),
            cust = requestCust
        )

        mallRepository.save(newData)

        return ResponseEntity.ok(
            MallRegisterResponseDto(mallId = newData.mallId)
        )
    }

 

추가로, 필터나 리졸버를 사용하려면 Configuration bean 등록을 해줘야한다.

 

1. filter

@Configuration
class FilterConfig (
    val custSessionRepository: CustSessionRepository
){
    @Bean
    fun authFilter(): FilterRegistrationBean<AuthFilter> {
        val registrationBean = FilterRegistrationBean<AuthFilter>()
        registrationBean.filter = AuthFilter(custSessionRepository)
        registrationBean.addUrlPatterns("/api/ch/*")  // 필터가 적용될 URL 패턴 지정
        return registrationBean
    }
}

 

 

2. resolve

@Configuration
class WebConfig : WebMvcConfigurer {
    override fun addArgumentResolvers(resolvers: MutableList<HandlerMethodArgumentResolver>) {
        resolvers.add(AuthConfig())
    }
}

 

끝.

'KOTLIN' 카테고리의 다른 글

Kotlin + Spring Boot 3.1.3 + QueryDsl gradle 적용  (0) 2023.09.28
Kotlin Nullable 문법 특징  (0) 2023.09.09
Kotlin 변수 type  (0) 2023.09.08

댓글