feat: Interceptor / Resolver 에 실패 로깅 및 성공시 member_id MDC 등록 추가

This commit is contained in:
이상진 2025-07-29 14:03:02 +09:00
parent 4db2b11970
commit 3157489399
2 changed files with 32 additions and 7 deletions

View File

@ -1,7 +1,10 @@
package roomescape.auth.web.support package roomescape.auth.web.support
import io.github.oshai.kotlinlogging.KLogger
import io.github.oshai.kotlinlogging.KotlinLogging
import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse import jakarta.servlet.http.HttpServletResponse
import org.slf4j.MDC
import org.springframework.stereotype.Component import org.springframework.stereotype.Component
import org.springframework.web.method.HandlerMethod import org.springframework.web.method.HandlerMethod
import org.springframework.web.servlet.HandlerInterceptor import org.springframework.web.servlet.HandlerInterceptor
@ -11,6 +14,8 @@ import roomescape.auth.infrastructure.jwt.JwtHandler
import roomescape.member.business.MemberService import roomescape.member.business.MemberService
import roomescape.member.infrastructure.persistence.MemberEntity import roomescape.member.infrastructure.persistence.MemberEntity
private val log: KLogger = KotlinLogging.logger {}
@Component @Component
class AuthInterceptor( class AuthInterceptor(
private val memberService: MemberService, private val memberService: MemberService,
@ -28,23 +33,29 @@ class AuthInterceptor(
return true return true
} }
val member: MemberEntity = findMember(request) val accessToken: String? = request.accessToken()
log.info { "[AuthInterceptor] 인증 시작. accessToken=${accessToken}" }
val member: MemberEntity = findMember(accessToken)
if (admin != null && !member.isAdmin()) { if (admin != null && !member.isAdmin()) {
log.info { "[AuthInterceptor] 관리자 인증 실패. memberId=${member.id}, role=${member.role}" }
throw AuthException(AuthErrorCode.ACCESS_DENIED) throw AuthException(AuthErrorCode.ACCESS_DENIED)
} }
MDC.put("member_id", "${member.id}")
log.info { "[AuthInterceptor] 인증 완료. memberId=${member.id}, role=${member.role}" }
return true return true
} }
private fun findMember(request: HttpServletRequest): MemberEntity { private fun findMember(accessToken: String?): MemberEntity {
try { try {
val token: String? = request.accessToken() val memberId = jwtHandler.getMemberIdFromToken(accessToken)
val memberId: Long = jwtHandler.getMemberIdFromToken(token)
return memberService.findById(memberId) return memberService.findById(memberId)
.also { MDC.put("member_id", "$memberId") }
} catch (e: Exception) { } catch (e: Exception) {
throw e log.info { "[AuthInterceptor] 회원 조회 실패. accessToken = ${accessToken}" }
val errorCode = AuthErrorCode.MEMBER_NOT_FOUND
throw AuthException(errorCode, e.message ?: errorCode.message)
} }
} }
} }

View File

@ -1,14 +1,21 @@
package roomescape.auth.web.support package roomescape.auth.web.support
import io.github.oshai.kotlinlogging.KLogger
import io.github.oshai.kotlinlogging.KotlinLogging
import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletRequest
import org.slf4j.MDC
import org.springframework.core.MethodParameter import org.springframework.core.MethodParameter
import org.springframework.stereotype.Component import org.springframework.stereotype.Component
import org.springframework.web.bind.support.WebDataBinderFactory import org.springframework.web.bind.support.WebDataBinderFactory
import org.springframework.web.context.request.NativeWebRequest import org.springframework.web.context.request.NativeWebRequest
import org.springframework.web.method.support.HandlerMethodArgumentResolver import org.springframework.web.method.support.HandlerMethodArgumentResolver
import org.springframework.web.method.support.ModelAndViewContainer import org.springframework.web.method.support.ModelAndViewContainer
import roomescape.auth.exception.AuthErrorCode
import roomescape.auth.exception.AuthException
import roomescape.auth.infrastructure.jwt.JwtHandler import roomescape.auth.infrastructure.jwt.JwtHandler
private val log: KLogger = KotlinLogging.logger {}
@Component @Component
class MemberIdResolver( class MemberIdResolver(
private val jwtHandler: JwtHandler private val jwtHandler: JwtHandler
@ -27,6 +34,13 @@ class MemberIdResolver(
val request: HttpServletRequest = webRequest.nativeRequest as HttpServletRequest val request: HttpServletRequest = webRequest.nativeRequest as HttpServletRequest
val token: String? = request.accessToken() val token: String? = request.accessToken()
try {
return jwtHandler.getMemberIdFromToken(token) return jwtHandler.getMemberIdFromToken(token)
.also { MDC.put("member_id", "$it") }
} catch (e: Exception) {
log.info { "[MemberIdResolver] 회원 조회 실패. message=${e.message}" }
val errorCode = AuthErrorCode.MEMBER_NOT_FOUND
throw AuthException(errorCode, e.message ?: errorCode.message)
}
} }
} }