본인인증 추가

This commit is contained in:
Klaus 2023-07-28 17:35:31 +09:00
parent ab116bb45b
commit 5b3b3a767f
7 changed files with 134 additions and 4 deletions

View File

@ -48,6 +48,9 @@ dependencies {
implementation("com.amazonaws:aws-java-sdk-s3:1.12.380") implementation("com.amazonaws:aws-java-sdk-s3:1.12.380")
implementation("com.amazonaws:aws-java-sdk-cloudfront:1.12.380") implementation("com.amazonaws:aws-java-sdk-cloudfront:1.12.380")
// bootpay
implementation("io.github.bootpay:backend:2.2.1")
developmentOnly("org.springframework.boot:spring-boot-devtools") developmentOnly("org.springframework.boot:spring-boot-devtools")
runtimeOnly("com.h2database:h2") runtimeOnly("com.h2database:h2")
runtimeOnly("com.mysql:mysql-connector-j") runtimeOnly("com.mysql:mysql-connector-j")

View File

@ -2,7 +2,6 @@ package kr.co.vividnext.sodalive.member.auth
import kr.co.vividnext.sodalive.common.BaseEntity import kr.co.vividnext.sodalive.common.BaseEntity
import kr.co.vividnext.sodalive.member.Member import kr.co.vividnext.sodalive.member.Member
import javax.persistence.CascadeType
import javax.persistence.Column import javax.persistence.Column
import javax.persistence.Entity import javax.persistence.Entity
import javax.persistence.FetchType import javax.persistence.FetchType
@ -18,10 +17,12 @@ data class Auth(
@Column(columnDefinition = "TEXT", nullable = false) @Column(columnDefinition = "TEXT", nullable = false)
val uniqueCi: String, val uniqueCi: String,
@Column(columnDefinition = "TEXT", nullable = false) @Column(columnDefinition = "TEXT", nullable = false)
val di: String val di: String,
@Column(nullable = false)
val gender: Int
) : BaseEntity() { ) : BaseEntity() {
@OneToOne(fetch = FetchType.LAZY, cascade = [CascadeType.ALL]) @OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id", nullable = true) @JoinColumn(name = "member_id", nullable = false)
var member: Member? = null var member: Member? = null
set(value) { set(value) {
value?.auth = this value?.auth = this

View File

@ -0,0 +1,24 @@
package kr.co.vividnext.sodalive.member.auth
import kr.co.vividnext.sodalive.common.ApiResponse
import kr.co.vividnext.sodalive.common.SodaException
import kr.co.vividnext.sodalive.member.Member
import org.springframework.security.core.annotation.AuthenticationPrincipal
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("/auth")
class AuthController(private val service: AuthService) {
@PostMapping
fun authVerify(
@RequestBody request: AuthVerifyRequest,
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
) = run {
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
ApiResponse.ok(service.verify(member, request))
}
}

View File

@ -0,0 +1,7 @@
package kr.co.vividnext.sodalive.member.auth
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository
@Repository
interface AuthRepository : JpaRepository<Auth, Long>

View File

@ -0,0 +1,62 @@
package kr.co.vividnext.sodalive.member.auth
import com.fasterxml.jackson.databind.ObjectMapper
import kr.co.bootpay.Bootpay
import kr.co.vividnext.sodalive.common.SodaException
import kr.co.vividnext.sodalive.member.Member
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.time.LocalDate
@Service
@Transactional(readOnly = true)
class AuthService(
private val repository: AuthRepository,
private val objectMapper: ObjectMapper,
@Value("\${bootpay.application-id}")
private val bootpayApplicationId: String,
@Value("\${bootpay.private-key}")
private val bootpayPrivateKey: String
) {
@Transactional
fun verify(member: Member, request: AuthVerifyRequest) {
val bootpay = Bootpay(bootpayApplicationId, bootpayPrivateKey)
try {
val token = bootpay.accessToken
if (token["error_code"] != null) throw SodaException("인증정보에 오류가 있습니다.\n다시 시도해 주세요.")
val res = bootpay.certificate(request.receiptId)
val certificateResult = objectMapper.convertValue(res, AuthCertificateResult::class.java)
if (
certificateResult.status == 12 &&
certificateResult.statusLocale == "본인인증완료" &&
certificateResult.receiptId == request.receiptId
) {
val certificate = certificateResult.authenticateData
val nowYear = LocalDate.now().year
val certificateYear = certificate.birth.substring(0, 4).toInt()
if (nowYear - certificateYear >= 19) {
val auth = Auth(
name = certificate.name,
birth = certificate.birth,
uniqueCi = certificate.unique,
di = certificate.di,
gender = certificate.gender
)
auth.member = member
repository.save(auth)
} else {
throw SodaException("19세 미만 인증 오류")
}
} else {
throw SodaException("인증정보에 오류가 있습니다.\n다시 시도해 주세요.")
}
} catch (e: Exception) {
throw SodaException("인증정보에 오류가 있습니다.\n다시 시도해 주세요.")
}
}
}

View File

@ -0,0 +1,29 @@
package kr.co.vividnext.sodalive.member.auth
import com.fasterxml.jackson.annotation.JsonProperty
data class AuthVerifyRequest(
@JsonProperty("receipt_id")
val receiptId: String,
@JsonProperty("version")
val version: String?
)
data class AuthVerifyCertificate(
val name: String,
val birth: String,
val unique: String,
val di: String,
val gender: Int
)
data class AuthCertificateResult(
@JsonProperty("receipt_id")
val receiptId: String,
@JsonProperty("status")
val status: Int,
@JsonProperty("status_locale")
val statusLocale: String,
@JsonProperty("authenticate_data")
val authenticateData: AuthVerifyCertificate
)

View File

@ -8,6 +8,10 @@ logging:
util: util:
EC2MetadataUtils: error EC2MetadataUtils: error
bootpay:
applicationId: ${BOOTPAY_APPLICATION_ID}
privateKey: ${BOOTPAY_PRIVATE_KEY}
cloud: cloud:
aws: aws:
credentials: credentials: