-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat Account Module에 Token Validation Domain 작성 #13
- Loading branch information
1 parent
997dba2
commit 37bbd9c
Showing
12 changed files
with
292 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 8 additions & 0 deletions
8
delivery-java-project/acount/src/main/kotlin/org/delivery/account/common/Log.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package org.delivery.account.common | ||
|
||
import org.slf4j.Logger | ||
import org.slf4j.LoggerFactory | ||
|
||
interface Log { | ||
val log: Logger get() = LoggerFactory.getLogger(this.javaClass) | ||
} |
47 changes: 47 additions & 0 deletions
47
...ect/acount/src/main/kotlin/org/delivery/account/config/objectmapper/ObjectMapperConfig.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package org.delivery.account.config.objectmapper | ||
|
||
import com.fasterxml.jackson.databind.DeserializationFeature | ||
import com.fasterxml.jackson.databind.ObjectMapper | ||
import com.fasterxml.jackson.databind.PropertyNamingStrategies | ||
import com.fasterxml.jackson.databind.SerializationFeature | ||
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module | ||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule | ||
import com.fasterxml.jackson.module.kotlin.KotlinFeature | ||
import com.fasterxml.jackson.module.kotlin.KotlinModule | ||
import org.springframework.context.annotation.Bean | ||
import org.springframework.context.annotation.Configuration | ||
|
||
@Configuration | ||
class ObjectMapperConfig { | ||
@Bean | ||
fun objectMapper(): ObjectMapper { | ||
val kotlinModule = KotlinModule | ||
.Builder() | ||
.apply { | ||
withReflectionCacheSize(512) | ||
/// List가 들어왔을 때 | ||
// true => 사이즈 0인 리스트, false => null | ||
configure(KotlinFeature.NullToEmptyCollection, false) | ||
configure(KotlinFeature.NullToEmptyMap, true) | ||
configure(KotlinFeature.NullIsSameAsDefault, false) | ||
configure(KotlinFeature.SingletonSupport, false) | ||
configure(KotlinFeature.StrictNullChecks, false) | ||
} | ||
.build() | ||
|
||
val objectMapper = ObjectMapper().apply { | ||
registerModule(Jdk8Module()) | ||
registerModule(JavaTimeModule()) | ||
registerModule(kotlinModule) | ||
|
||
configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) | ||
configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false) | ||
|
||
disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) | ||
|
||
propertyNamingStrategy = PropertyNamingStrategies.SNAKE_CASE | ||
} | ||
|
||
return objectMapper | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
...-java-project/acount/src/main/kotlin/org/delivery/account/config/swagger/SwaggerConfig.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package org.delivery.account.config.swagger | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper | ||
import io.swagger.v3.core.jackson.ModelResolver | ||
import org.springframework.context.annotation.Bean | ||
import org.springframework.context.annotation.Configuration | ||
|
||
@Configuration | ||
class SwaggerConfig { | ||
@Bean | ||
fun modelResolver( | ||
objectMapper: ObjectMapper | ||
) : ModelResolver { | ||
return ModelResolver(objectMapper) | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
...roject/acount/src/main/kotlin/org/delivery/account/domain/token/business/TokenBusiness.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package org.delivery.account.domain.token.business | ||
|
||
import org.delivery.account.domain.token.controller.model.TokenValidationRequest | ||
import org.delivery.account.domain.token.controller.model.TokenValidationResponse | ||
import org.delivery.account.domain.token.model.TokenDto | ||
import org.delivery.account.domain.token.service.TokenService | ||
import org.delivery.common.annotation.Business | ||
|
||
@Business | ||
class TokenBusiness( | ||
private val tokenService: TokenService, | ||
) { | ||
fun tokenValidation(tokenValidationRequest: TokenValidationRequest?): TokenValidationResponse? { | ||
val result = tokenService.validationTokenWithThrow(tokenValidationRequest?.tokenDto?.token) | ||
|
||
return TokenValidationResponse( | ||
userId = result | ||
) | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
...src/main/kotlin/org/delivery/account/domain/token/controller/TokenPrivateApiController.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package org.delivery.account.domain.token.controller | ||
|
||
import org.delivery.account.common.Log | ||
import org.delivery.account.domain.token.business.TokenBusiness | ||
import org.delivery.account.domain.token.controller.model.TokenValidationRequest | ||
import org.delivery.account.domain.token.controller.model.TokenValidationResponse | ||
import org.springframework.web.bind.annotation.PostMapping | ||
import org.springframework.web.bind.annotation.RequestBody | ||
import org.springframework.web.bind.annotation.RequestMapping | ||
import org.springframework.web.bind.annotation.RestController | ||
|
||
@RestController | ||
@RequestMapping("/private-api/token") | ||
class TokenPrivateApiController ( | ||
private val tokenBusiness: TokenBusiness | ||
){ | ||
companion object: Log | ||
|
||
@PostMapping("/validation") | ||
fun tokenValidation( | ||
@RequestBody | ||
tokenValidationRequest: TokenValidationRequest? | ||
): TokenValidationResponse? { | ||
log.info("token validation init : $tokenValidationRequest") | ||
return tokenBusiness.tokenValidation(tokenValidationRequest) | ||
|
||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
.../main/kotlin/org/delivery/account/domain/token/controller/model/TokenValidationRequest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package org.delivery.account.domain.token.controller.model | ||
|
||
import org.delivery.account.domain.token.model.TokenDto | ||
|
||
data class TokenValidationRequest( | ||
val tokenDto: TokenDto? = null, | ||
) |
5 changes: 5 additions & 0 deletions
5
...main/kotlin/org/delivery/account/domain/token/controller/model/TokenValidationResponse.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package org.delivery.account.domain.token.controller.model | ||
|
||
data class TokenValidationResponse( | ||
val userId: Long? = null, | ||
) |
104 changes: 104 additions & 0 deletions
104
...project/acount/src/main/kotlin/org/delivery/account/domain/token/helper/JwtTokenHelper.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package org.delivery.account.domain.token.helper | ||
|
||
import io.jsonwebtoken.ExpiredJwtException | ||
import io.jsonwebtoken.Jwts | ||
import io.jsonwebtoken.SignatureAlgorithm | ||
import io.jsonwebtoken.security.Keys | ||
import io.jsonwebtoken.security.SignatureException | ||
import org.delivery.account.domain.token.ifs.TokenHelperIfs | ||
import org.delivery.account.domain.token.model.TokenDto | ||
import org.delivery.common.error.TokenError | ||
import org.delivery.common.exception.ApiException | ||
import org.springframework.beans.factory.annotation.Value | ||
import org.springframework.stereotype.Component | ||
import java.time.LocalDateTime | ||
import java.time.ZoneId | ||
import java.util.* | ||
|
||
@Component | ||
class JwtTokenHelper | ||
: TokenHelperIfs { | ||
// Spring.bean.factory.annotation.Value | ||
@Value("\${token.secret.key}") | ||
private val secretKey: String? = null | ||
|
||
@Value("\${token.access-token.plus-hour}") | ||
private val accessTokenPlushHour: Long = 1 | ||
|
||
@Value("\${token.refresh-token.plus-hour}") | ||
private val refreshTokenPlusHour: Long = 12 | ||
|
||
override fun issueAccessToken(data: Map<String, Any>?): TokenDto? { | ||
val expiredAtLocalDateTime = LocalDateTime | ||
.now() | ||
.plusHours(accessTokenPlushHour) | ||
|
||
val expiredAt = Date.from( | ||
expiredAtLocalDateTime | ||
.atZone(ZoneId.systemDefault()) | ||
.toInstant() | ||
) | ||
|
||
val key = Keys.hmacShaKeyFor(secretKey?.toByteArray()) | ||
|
||
val jwtToken = Jwts | ||
.builder() | ||
.signWith(key, SignatureAlgorithm.HS256) | ||
.setClaims(data) | ||
.setExpiration(expiredAt) | ||
.compact() | ||
|
||
return TokenDto(jwtToken, expiredAtLocalDateTime) | ||
} | ||
|
||
override fun issueRefreshToken(data: Map<String, Any>?): TokenDto? { | ||
val expiredAtLocalDateTime = LocalDateTime | ||
.now() | ||
.plusHours(refreshTokenPlusHour) | ||
|
||
val expiredAt = Date.from( | ||
expiredAtLocalDateTime | ||
.atZone(ZoneId.systemDefault()) | ||
.toInstant() | ||
) | ||
|
||
val key = Keys.hmacShaKeyFor(secretKey?.toByteArray()) | ||
|
||
val jwtToken = Jwts | ||
.builder() | ||
.signWith(key, SignatureAlgorithm.HS256) | ||
.setClaims(data) | ||
.setExpiration(expiredAt) | ||
.compact() | ||
|
||
return TokenDto(jwtToken, expiredAtLocalDateTime) | ||
} | ||
|
||
override fun validationTokenWithThrow(token: String?): Map<String, Any>? { | ||
val key = Keys.hmacShaKeyFor(secretKey?.toByteArray()) | ||
|
||
val parser = Jwts | ||
.parserBuilder() | ||
.setSigningKey(key) | ||
.build() | ||
|
||
return try { | ||
val result = token?.let { parser.parseClaimsJwt(it) } | ||
HashMap(result?.body) | ||
} catch (e: Exception) { | ||
when (e) { | ||
is SignatureException -> { | ||
throw ApiException(TokenError.INVALID_TOKEN) | ||
} | ||
|
||
is ExpiredJwtException -> { | ||
throw ApiException(TokenError.EXPIRED_TOKEN) | ||
} | ||
|
||
else -> { | ||
throw ApiException(TokenError.INVALID_TOKEN) | ||
} | ||
} | ||
} | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
...va-project/acount/src/main/kotlin/org/delivery/account/domain/token/ifs/TokenHelperIfs.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package org.delivery.account.domain.token.ifs | ||
|
||
import org.delivery.account.domain.token.model.TokenDto | ||
|
||
interface TokenHelperIfs { | ||
fun issueAccessToken(data: Map<String, Any>?): TokenDto? | ||
fun issueRefreshToken(data: Map<String, Any>?): TokenDto? | ||
fun validationTokenWithThrow(token: String?): Map<String, Any>? | ||
} |
8 changes: 8 additions & 0 deletions
8
...y-java-project/acount/src/main/kotlin/org/delivery/account/domain/token/model/TokenDto.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package org.delivery.account.domain.token.model | ||
|
||
import java.time.LocalDateTime | ||
|
||
data class TokenDto( | ||
val token: String? = null, | ||
val expiredAt: LocalDateTime? = null | ||
) |
37 changes: 37 additions & 0 deletions
37
...-project/acount/src/main/kotlin/org/delivery/account/domain/token/service/TokenService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package org.delivery.account.domain.token.service | ||
|
||
import org.delivery.account.domain.token.ifs.TokenHelperIfs | ||
import org.delivery.account.domain.token.model.TokenDto | ||
import org.springframework.stereotype.Service | ||
|
||
@Service | ||
class TokenService(private val tokenHelper: TokenHelperIfs) { | ||
fun issueAccessToken(userId: Long?): TokenDto? { | ||
return userId?.let { | ||
val data = mapOf("userId" to it) | ||
tokenHelper.issueAccessToken(data) | ||
} | ||
} | ||
|
||
fun issueRefreshToken(userId: Long?): TokenDto? { | ||
/// requiredNotNull 구문이 나오고 그 이후는 | ||
/// 그 안에 들어간 데이터가 NotNull임을 의미하고 Null일 경우 에러 발생 | ||
requireNotNull(userId) | ||
val data = mapOf("userId" to userId) | ||
return tokenHelper.issueRefreshToken(data) | ||
} | ||
|
||
fun validationTokenWithThrow(token: String?): Long? { | ||
// requireNotNull(token) | ||
// val map = tokenHelper.validationTokenWithThrow(token) | ||
// val userId = map?.get("userId") | ||
// requireNotNull(userId) | ||
// return userId.toString().toLong() | ||
|
||
return tokenHelper | ||
.validationTokenWithThrow(token) | ||
?.let { map -> | ||
map["userId"] | ||
}.toString().toLong() | ||
} | ||
} |