feat(ai-character): 관리자 API Phase 1 기반을 추가한다

This commit is contained in:
2026-07-26 05:01:34 +09:00
parent d3564f8c0d
commit 0d2742756f
19 changed files with 4108 additions and 16 deletions
@@ -1,12 +1,22 @@
package kr.co.vividnext.sodalive.common
import com.fasterxml.jackson.databind.ObjectMapper
import io.jsonwebtoken.JwtException
import org.springframework.security.authentication.BadCredentialsException
import org.springframework.security.web.AuthenticationEntryPoint
import org.springframework.security.web.util.matcher.RequestMatcher
import org.springframework.web.filter.OncePerRequestFilter
import org.springframework.web.servlet.HandlerExceptionResolver
import javax.servlet.FilterChain
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
class ExceptionHandlerFilter(private val objectMapper: ObjectMapper) : OncePerRequestFilter() {
class ExceptionHandlerFilter(
private val objectMapper: ObjectMapper,
private val apiRequestMatcher: RequestMatcher,
private val apiAuthenticationEntryPoint: AuthenticationEntryPoint,
private val apiExceptionResolver: HandlerExceptionResolver
) : OncePerRequestFilter() {
override fun doFilterInternal(
request: HttpServletRequest,
response: HttpServletResponse,
@@ -15,6 +25,18 @@ class ExceptionHandlerFilter(private val objectMapper: ObjectMapper) : OncePerRe
try {
filterChain.doFilter(request, response)
} catch (e: Exception) {
if (apiRequestMatcher.matches(request)) {
if (isAuthenticationFailure(e)) {
val authenticationException = e as? BadCredentialsException
?: BadCredentialsException("Authentication failed", e)
apiAuthenticationEntryPoint.commence(request, response, authenticationException)
} else {
val resolved = apiExceptionResolver.resolveException(request, response, null, e)
if (resolved == null) throw e
}
return
}
response.status = 401
response.contentType = "application/json"
response.characterEncoding = "UTF-8"
@@ -23,4 +45,10 @@ class ExceptionHandlerFilter(private val objectMapper: ObjectMapper) : OncePerRe
response.writer.write(json)
}
}
private fun isAuthenticationFailure(exception: Exception): Boolean {
return exception is JwtException ||
exception is BadCredentialsException ||
(exception is SodaException && exception.messageKey == "common.error.bad_credentials")
}
}