[#43] feat: client ip 추출 기능 추가

- client ip 후보군 enum 생성
- security, logging에 대한 패키지화(infra)
This commit is contained in:
beaniejoy
2023-04-15 21:20:08 +09:00
parent 743fe11dc6
commit 5d516c95b6
17 changed files with 59 additions and 37 deletions

View File

@@ -1,9 +1,9 @@
package io.beaniejoy.dongnecafe.common.config
import io.beaniejoy.dongnecafe.utils.security.JwtTokenUtils
import io.beaniejoy.dongnecafe.security.config.JwtAuthenticationConfigurer
import io.beaniejoy.dongnecafe.security.handler.CustomAccessDeniedHandler
import io.beaniejoy.dongnecafe.security.handler.CustomAuthenticationEntryPoint
import io.beaniejoy.dongnecafe.infra.security.config.JwtAuthenticationConfigurer
import io.beaniejoy.dongnecafe.infra.security.handler.CustomAccessDeniedHandler
import io.beaniejoy.dongnecafe.infra.security.handler.CustomAuthenticationEntryPoint
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.autoconfigure.security.servlet.PathRequest
import org.springframework.context.annotation.Bean

View File

@@ -1,6 +1,7 @@
package io.beaniejoy.dongnecafe.security
import io.beaniejoy.dongnecafe.common.error.constant.ErrorCode
import io.beaniejoy.dongnecafe.infra.security.SecurityUser
import mu.KLogging
import org.springframework.security.authentication.AuthenticationProvider
import org.springframework.security.authentication.BadCredentialsException

View File

@@ -4,6 +4,7 @@ import io.beaniejoy.dongnecafe.common.error.constant.ErrorCode
import io.beaniejoy.dongnecafe.common.error.exception.BusinessException
import io.beaniejoy.dongnecafe.domain.member.entity.Member
import io.beaniejoy.dongnecafe.domain.member.repository.MemberRepository
import io.beaniejoy.dongnecafe.infra.security.SecurityUser
import mu.KLogging
import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.security.core.userdetails.UserDetailsService

View File

@@ -1,9 +1,6 @@
package io.beaniejoy.dongnecafe.infra
package io.beaniejoy.dongnecafe.infra.logging
import io.beaniejoy.dongnecafe.utils.logging.getRequestBody
import io.beaniejoy.dongnecafe.utils.logging.getRequestHeaders
import io.beaniejoy.dongnecafe.utils.logging.getRequestParams
import io.beaniejoy.dongnecafe.utils.logging.getResponseBody
import io.beaniejoy.dongnecafe.utils.logging.*
import org.springframework.http.HttpStatus
import org.springframework.web.util.ContentCachingRequestWrapper
import org.springframework.web.util.ContentCachingResponseWrapper
@@ -30,7 +27,7 @@ data class HttpLogMessage(
httpMethod = requestWrapper.method,
requestUri = requestWrapper.requestURI,
httpStatus = HttpStatus.valueOf(responseWrapper.status),
clientIp = requestWrapper.remoteAddr,
clientIp = requestWrapper.getClientIp(),
elapsedTime = elapsedTime,
headers = requestWrapper.getRequestHeaders(),
requestParam = requestWrapper.getRequestParams(),

View File

@@ -1,4 +1,4 @@
package io.beaniejoy.dongnecafe.infra
package io.beaniejoy.dongnecafe.infra.logging
import mu.KotlinLogging
import org.slf4j.MDC
@@ -15,7 +15,7 @@ import javax.servlet.http.HttpServletResponse
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
class RequestResponseLoggingFilter : OncePerRequestFilter() {
class ReqResLoggingFilter : OncePerRequestFilter() {
private val log = KotlinLogging.logger {}
companion object {
@@ -49,9 +49,9 @@ class RequestResponseLoggingFilter : OncePerRequestFilter() {
cachingResponseWrapper.copyBodyToResponse()
} catch (e: Exception) {
log.error(e) { "[RequestResponseLoggingFilter] logging 실패" }
} finally {
MDC.remove(REQUEST_ID)
log.error(e) { "[${this::class.simpleName}] Logging 실패" }
}
MDC.remove(REQUEST_ID)
}
}

View File

@@ -0,0 +1,17 @@
package io.beaniejoy.dongnecafe.infra.logging.constant
/**
* http request client ip possible enum list
* (ref. https://blog.yevgnenll.me/posts/find-client-ip-from-http-request-header)
* @property headerName String client ip header name
*/
enum class HttpClientIp(
val headerName: String,
) {
X_FORWARDED_FOR("X-Forwarded-For"),
PROXY_CLIENT_IP("Proxy-Client-IP"),
WL_PROXY_CLIENT_IP("WL-Proxy-Client-IP"),
HTTP_X_FORWARDED("HTTP_X_FORWARDED"),
HTTP_X_FORWARDED_FOR("HTTP_X_FORWARDED_FOR"),
HTTP_CLIENT_IP("HTTP_CLIENT_IP")
}

View File

@@ -1,4 +1,4 @@
package io.beaniejoy.dongnecafe.security
package io.beaniejoy.dongnecafe.infra.security
import io.beaniejoy.dongnecafe.domain.member.entity.Member
import org.springframework.security.core.GrantedAuthority

View File

@@ -1,6 +1,6 @@
package io.beaniejoy.dongnecafe.security.config
package io.beaniejoy.dongnecafe.infra.security.config
import io.beaniejoy.dongnecafe.security.filter.JwtAuthenticationFilter
import io.beaniejoy.dongnecafe.infra.security.filter.JwtAuthenticationFilter
import io.beaniejoy.dongnecafe.utils.security.JwtTokenUtils
import org.springframework.security.config.annotation.SecurityConfigurerAdapter
import org.springframework.security.config.annotation.web.builders.HttpSecurity

View File

@@ -1,4 +1,4 @@
package io.beaniejoy.dongnecafe.security.constant
package io.beaniejoy.dongnecafe.infra.security.constant
object SecurityConstant {
const val BEARER = "Bearer"

View File

@@ -1,8 +1,8 @@
package io.beaniejoy.dongnecafe.security.filter
package io.beaniejoy.dongnecafe.infra.security.filter
import io.beaniejoy.dongnecafe.utils.security.JwtTokenUtils
import io.beaniejoy.dongnecafe.security.constant.SecurityConstant.BEARER
import io.beaniejoy.dongnecafe.security.constant.SecurityConstant.WHITESPACE
import io.beaniejoy.dongnecafe.infra.security.constant.SecurityConstant.BEARER
import io.beaniejoy.dongnecafe.infra.security.constant.SecurityConstant.WHITESPACE
import mu.KotlinLogging
import org.springframework.http.HttpHeaders
import org.springframework.security.core.context.SecurityContextHolder

View File

@@ -1,4 +1,4 @@
package io.beaniejoy.dongnecafe.security.handler
package io.beaniejoy.dongnecafe.infra.security.handler
import mu.KLogging
import org.springframework.security.access.AccessDeniedException

View File

@@ -1,4 +1,4 @@
package io.beaniejoy.dongnecafe.security.handler
package io.beaniejoy.dongnecafe.infra.security.handler
import mu.KLogging
import org.springframework.security.core.AuthenticationException

View File

@@ -1,6 +1,7 @@
package io.beaniejoy.dongnecafe.utils.logging
import com.google.gson.Gson
import io.beaniejoy.dongnecafe.infra.logging.constant.HttpClientIp
import org.springframework.web.util.ContentCachingRequestWrapper
import org.springframework.web.util.ContentCachingResponseWrapper
import javax.servlet.http.HttpServletRequest
@@ -22,6 +23,18 @@ fun HttpServletRequest.getRequestParams(): String {
}.entries.joinToString("&")
}
fun HttpServletRequest.getClientIp(): String {
HttpClientIp.values().forEach { clientIpHeader ->
this.getHeader(clientIpHeader.headerName).also {
if (it.isNullOrBlank().not() && "unknown".equals(it, true).not()) {
return it
}
}
}
return this.remoteAddr
}
fun ContentCachingRequestWrapper.getRequestBody(): String {
return this.contentAsByteArray.toString(Charsets.UTF_8)
}

View File

@@ -1,7 +0,0 @@
package io.beaniejoy.dongnecafe.utils.logging
class LoggingUtils {
companion object {
}
}

View File

@@ -1,7 +1,7 @@
package io.beaniejoy.dongnecafe.utils.security
import io.beaniejoy.dongnecafe.security.SecurityUser
import io.beaniejoy.dongnecafe.security.constant.SecurityConstant.JWT_AUTHORITIES_KEY
import io.beaniejoy.dongnecafe.infra.security.SecurityUser
import io.beaniejoy.dongnecafe.infra.security.constant.SecurityConstant.JWT_AUTHORITIES_KEY
import io.jsonwebtoken.Claims
import io.jsonwebtoken.ExpiredJwtException
import io.jsonwebtoken.Jwts

View File

@@ -1,7 +1,7 @@
package io.beaniejoy.dongnecafe.utils.security
import io.beaniejoy.dongnecafe.security.constant.SecurityConstant.ANONYMOUS_USER
import io.beaniejoy.dongnecafe.security.constant.SecurityConstant.ROLE_ANONYMOUS
import io.beaniejoy.dongnecafe.infra.security.constant.SecurityConstant.ANONYMOUS_USER
import io.beaniejoy.dongnecafe.infra.security.constant.SecurityConstant.ROLE_ANONYMOUS
import org.springframework.security.core.Authentication
fun Authentication.getAuthPrincipal() : String? {

View File

@@ -1,9 +1,9 @@
package io.beaniejoy.dongnecafe.common.config
import io.beaniejoy.dongnecafe.security.config.JwtAuthenticationConfigurer
import io.beaniejoy.dongnecafe.infra.security.config.JwtAuthenticationConfigurer
import io.beaniejoy.dongnecafe.utils.security.JwtTokenUtils
import io.beaniejoy.dongnecafe.security.handler.CustomAccessDeniedHandler
import io.beaniejoy.dongnecafe.security.handler.CustomAuthenticationEntryPoint
import io.beaniejoy.dongnecafe.infra.security.handler.CustomAccessDeniedHandler
import io.beaniejoy.dongnecafe.infra.security.handler.CustomAuthenticationEntryPoint
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.autoconfigure.security.servlet.PathRequest
import org.springframework.context.annotation.Bean