처음 필터 단에서 내 나름대로 설계한 인증이 필요한 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 |
댓글