[#41] modify: 전체적인 리팩토링

- Security 관련 JWT filter, configurer 공통 코드 common 모듈화
- flyway 불필요한 설정 제거
This commit is contained in:
beaniejoy
2023-04-12 00:49:38 +09:00
parent ac40f5b42a
commit e95349f743
13 changed files with 25 additions and 102 deletions

View File

@@ -1,6 +1,6 @@
package io.beaniejoy.dongnecafe.common.config
import io.beaniejoy.dongnecafe.security.JwtTokenUtils
import io.beaniejoy.dongnecafe.security.utils.JwtTokenUtils
import io.beaniejoy.dongnecafe.security.config.JwtAuthenticationConfigurer
import io.beaniejoy.dongnecafe.security.handler.CustomAccessDeniedHandler
import io.beaniejoy.dongnecafe.security.handler.CustomAuthenticationEntryPoint

View File

@@ -1,7 +1,7 @@
package io.beaniejoy.dongnecafe.controller
import io.beaniejoy.dongnecafe.common.response.ApplicationResponse
import io.beaniejoy.dongnecafe.security.JwtTokenUtils
import io.beaniejoy.dongnecafe.security.utils.JwtTokenUtils
import io.beaniejoy.dongnecafe.domain.member.model.request.SignInRequest
import io.beaniejoy.dongnecafe.model.TokenResponse
import io.beaniejoy.dongnecafe.service.AuthService

View File

@@ -1,52 +0,0 @@
package io.beaniejoy.dongnecafe.security.filter
import io.beaniejoy.dongnecafe.security.JwtTokenUtils
import io.beaniejoy.dongnecafe.security.constant.SecurityConstant.BEARER
import io.beaniejoy.dongnecafe.security.constant.SecurityConstant.WHITESPACE
import mu.KotlinLogging
import org.springframework.http.HttpHeaders
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.web.filter.GenericFilterBean
import javax.servlet.FilterChain
import javax.servlet.ServletRequest
import javax.servlet.ServletResponse
import javax.servlet.http.HttpServletRequest
class JwtAuthenticationFilter(
private val jwtTokenUtils: JwtTokenUtils
) : GenericFilterBean() {
private val log = KotlinLogging.logger {}
/**
* JWT access token 인증 처리
*/
override fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
val httpRequest = request as HttpServletRequest
log.info { "[JwtAuthenticationFilter][${request.dispatcherType}] uri: ${request.requestURI}" }
getAccessToken(httpRequest)?.let {
jwtTokenUtils.getAuthentication(it)
}?.also {
SecurityContextHolder.getContext().authentication = it
log.info { "Valid Access Token [${it.name}]" }
}
chain.doFilter(request, response)
}
private fun getAccessToken(request: HttpServletRequest): String? {
val bearer = request.getHeader(HttpHeaders.AUTHORIZATION)
?: return null
val splitBearer = bearer.split(WHITESPACE)
if (splitBearer.first() != BEARER) {
return null
}
if (splitBearer.size != 2 || splitBearer.last().isBlank()) {
return null
}
return splitBearer.last()
}
}

View File

@@ -1,3 +1,6 @@
server:
port: 9090
spring:
profiles:
active: local
@@ -5,22 +8,17 @@ spring:
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: none # use flyway migration
ddl-auto: none
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
dialect: org.hibernate.dialect.MySQL8Dialect
format_sql: true
show-sql: false
open-in-view:
flyway:
enabled: false
devtools:
livereload:
enabled: false # no use devtools' LiveReload Server
server:
port: 9090
logging:
level:
org.hibernate.SQL: debug # logger 통해 로깅

View File

@@ -1,6 +1,6 @@
package io.beaniejoy.dongnecafe.common.config
import io.beaniejoy.dongnecafe.security.getAuthPrincipal
import io.beaniejoy.dongnecafe.security.utils.getAuthPrincipal
import mu.KLogging
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

View File

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

View File

@@ -6,4 +6,6 @@ object SecurityConstant {
const val ANONYMOUS_USER = "anonymousUser"
const val ROLE_ANONYMOUS = "ROLE_ANONYMOUS"
const val JWT_AUTHORITIES_KEY = "authorities"
}

View File

@@ -1,6 +1,6 @@
package io.beaniejoy.dongnecafe.security.filter
import io.beaniejoy.dongnecafe.security.JwtTokenUtils
import io.beaniejoy.dongnecafe.security.utils.JwtTokenUtils
import io.beaniejoy.dongnecafe.security.constant.SecurityConstant.BEARER
import io.beaniejoy.dongnecafe.security.constant.SecurityConstant.WHITESPACE
import mu.KotlinLogging

View File

@@ -1,5 +1,7 @@
package io.beaniejoy.dongnecafe.security
package io.beaniejoy.dongnecafe.security.utils
import io.beaniejoy.dongnecafe.security.SecurityUser
import io.beaniejoy.dongnecafe.security.constant.SecurityConstant.JWT_AUTHORITIES_KEY
import io.jsonwebtoken.Claims
import io.jsonwebtoken.ExpiredJwtException
import io.jsonwebtoken.Jwts
@@ -24,9 +26,7 @@ class JwtTokenUtils(
private val key: Key = Keys.hmacShaKeyFor(secretKey.toByteArray())
private val validityTimeMilliSec: Long = validityTimeSec * 1000
companion object : KLogging() {
const val AUTHORITIES_KEY = "authorities"
}
companion object : KLogging()
fun createToken(authentication: Authentication): String {
val authenticatedMember = (authentication.principal as SecurityUser).member
@@ -37,7 +37,7 @@ class JwtTokenUtils(
return Jwts.builder()
.setSubject(authenticatedMember.email)
.claim(AUTHORITIES_KEY, authorities)
.claim(JWT_AUTHORITIES_KEY, authorities)
.signWith(key, SignatureAlgorithm.HS256)
.setExpiration(expirationDate)
.compact()
@@ -47,7 +47,7 @@ class JwtTokenUtils(
val claims = getValidTokenBody(accessToken)
?: return null
val authorities = claims[AUTHORITIES_KEY].toString().split(",")
val authorities = claims[JWT_AUTHORITIES_KEY].toString().split(",")
.map { SimpleGrantedAuthority(it) }
return UsernamePasswordAuthenticationToken(claims.subject, accessToken, authorities)
@@ -62,10 +62,10 @@ class JwtTokenUtils(
.parseClaimsJws(accessToken)
.body
} catch (e: ExpiredJwtException) {
logger.error { "JWT access token expired. > Error: ${e.message}" }
logger.info { "JWT access token expired. > Error: ${e.message}" }
null
} catch (e: Exception) {
logger.error { "JWT access token invalid. > Error: ${e.message}" }
logger.info { "JWT access token invalid. > Error: ${e.message}" }
null
}
}

View File

@@ -1,4 +1,4 @@
package io.beaniejoy.dongnecafe.security
package io.beaniejoy.dongnecafe.security.utils
import io.beaniejoy.dongnecafe.security.constant.SecurityConstant.ANONYMOUS_USER
import io.beaniejoy.dongnecafe.security.constant.SecurityConstant.ROLE_ANONYMOUS

View File

@@ -1,7 +1,7 @@
package io.beaniejoy.dongnecafe.common.config
import io.beaniejoy.dongnecafe.security.JwtAuthenticationConfigurer
import io.beaniejoy.dongnecafe.security.JwtTokenUtils
import io.beaniejoy.dongnecafe.security.config.JwtAuthenticationConfigurer
import io.beaniejoy.dongnecafe.security.utils.JwtTokenUtils
import io.beaniejoy.dongnecafe.security.handler.CustomAccessDeniedHandler
import io.beaniejoy.dongnecafe.security.handler.CustomAuthenticationEntryPoint
import org.springframework.beans.factory.annotation.Autowired

View File

@@ -1,25 +0,0 @@
package io.beaniejoy.dongnecafe.security
import io.beaniejoy.dongnecafe.security.filter.JwtAuthenticationFilter
import org.springframework.security.config.annotation.SecurityConfigurerAdapter
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.web.DefaultSecurityFilterChain
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
class JwtAuthenticationConfigurer :
SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity>() {
private lateinit var jwtTokenUtils: JwtTokenUtils
override fun configure(http: HttpSecurity) {
http
.addFilterBefore(
JwtAuthenticationFilter(this.jwtTokenUtils),
UsernamePasswordAuthenticationFilter::class.java
)
}
fun jwtTokenUtils(jwtTokenUtils: JwtTokenUtils): JwtAuthenticationConfigurer {
this.jwtTokenUtils = jwtTokenUtils
return this
}
}

View File

@@ -5,10 +5,10 @@ spring:
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
hibernate:
ddl-auto: none # flyway migration 사용
ddl-auto: none
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
dialect: org.hibernate.dialect.MySQL8Dialect
format_sql: true
show-sql: false
devtools: