1. 요약
작업 중인 포스트입니다.
본 가이드에서는 Spring과 Vue를 사용하여 PASS 기반의 본인인증 프로세스를 소개합니다.
주요 흐름은 다음과 같이 3단계로 나뉩니다.
가. 인증요청
graph LR A[클라이언트] -->|1. '본인 인증 URL 생성' API 호출| B[서버] B -->|2. '본인 인증 URL' 반환| A A -->|3. 본인 인증 팝업창 띄우기| A
Mermaid
복사
나. 인증결과 반환
graph LR A[클라이언트] -->|4. 인증결과 요청| C C[인증 서비스] -->|5. 'Return URL'로 리다이렉트 및 인증결과 반환| A
Mermaid
복사
다. 인증결과 후처리
graph LR A[클라이언트] --> |6. 리다이렉트된 페이지에서 인증결과 추출| A A -->|7. 인증결과 복호화 및 유효성 검사 요청| B[서버] B -->|8. 복호화된 인증결과 응답| A
Mermaid
복사
2. Spring 기반 백엔드 구현
가. '본인 인증 URL' 생성 및 응답
1) API 설계
•
Endpoint: POST {{host}}/acc/v1/identities
•
Description: 클라이언트에서 제공하는 정보를 바탕으로 본인 인증 URL을 생성하고 반환합니다.
•
Request Parameters: callbackUrl, isMobile
•
Response: identityUrl
// 요청 예시
POST {{host}}/acc/v1/identities?callbackUrl=https://test.xxx.com:3000/signup/auth&isMobile=false
Headers:
Cookie: {본인 인증 정보}
// 응답 예시
200 OK
{
"identityUrl": "..."
}
JSON
복사
2) Application Service Logic
•
UserIdentityService 클래스: 본인 인증 URL을 생성하는 비즈니스 로직을 처리합니다.
•
createUrl 함수: Unique ID를 생성하여 URL을 만들기 위해 urlGenerator이라는 별도의 추상화 객체를 정의합니다.
@Service
class UserIdentityService(
private val urlGenerator: UrlGenerator,
private val requestRepository: IdentityRequestRepository,
) {
// 본인 인증 URL을 생성하는 함수
@Transactional
fun createUrl(cmd: IdentityRequestUrlCommand): IdentityRequestUrlDto {
// 사용자의 ID와 유니크한 키를 생성하여 저장합니다.
val request = requestRepository.save(IdentityRequest(userId = cmd.userId, key = UniqueIdMaker.id()))
// 저장된 요청 정보와 함께 URL을 생성합니다.
val url = urlGenerator.generate(request, cmd.isMobile, cmd.callbackUrl)
// 생성된 URL을 DTO 객체로 반환합니다.
return IdentityRequestUrlDto(url)
}
}
Kotlin
복사
나. 인증결과 복호화 및 유효성 검사 처리
1) API 설계
•
Endpoint: POST {{host}}/acc/v1/identities/verify
•
Description: 암호화된 본인 인증 결과를 검증하고, 검증된 정보를 반환합니다.
•
Request Body: 암호화된 본인 인증 데이터
•
Response: 200 OK
// 요청 예시
POST {{host}}/acc/v1/identities/verify
Headers:
Cookie: {본인 인증 정보}
Content-Type: application/json
{
"data": "{encrypted identity data}"
}
// 응답 예시
200 OK
JSON
복사
2) Application Service Logic
•
verify 함수: IdentityVerifier를 사용하여 암호화된 본인인증 데이터를 검증합니다.
•
UserIdentityFactory: 이전에 본인 인증되지 않은 사용자라면 본인 인증 정보를 저장합니다. 하지만 이미 본인 인증 정보가 저장된 사용자라면 최신 인증 정보로 기존 인증 정보를 업데이트합니다.
@Service
class UserIdentityService(
private val verifier: IdentityVerifier,
private val repository: UserIdentityRepository,
private val requestRepository: IdentityRequestRepository
) {
private val factory = UserIdentityFactory() // 본인 인증 객체 팩토리
private val logger = LoggerFactory.getLogger(javaClass) // 로그 객체
// 본인 인증 데이터를 검증하는 함수
@Transactional
fun verify(cmd: UserIdentityCommand): UserIdentityDto {
// 인증 데이터를 검증합니다.
val verified = verifier.verify(cmd.data)
logger.info("verify user identity result code: ${verified.resultCode}, userId: ${cmd.userId}")
// 검증 요청을 조회합니다.
val request = requestRepository.get(verified.reqNum) ?: throw IllegalStateException("유효하지 않은 '본인 인증결과'입니다")
if (request.userId != cmd.userId) throw IllegalStateException("다른 사용자의 '본인 인증결과'입니다")
// 새로운 본인 인증 정보를 생성합니다.
val newIdentity = factory.create(cmd.userId, data = verified)
// 기존 본인 인증 정보를 조회합니다.
val oldIdentity = repository.get(cmd.userId)
if (oldIdentity != null) {
// 기존 정보가 있으면 업데이트 합니다.
oldIdentity.replace(newIdentity.profile)
return UserIdentityDto(oldIdentity.phoneNumber)
}
// 새로운 본인 인증 정보를 저장하고 반환합니다.
repository.save(newIdentity)
return UserIdentityDto(newIdentity.phoneNumber)
}
}
Kotlin
복사
3. Vue 기반 프런트엔드 구현
가. '본인 인증 URL 생성' 처리
1) 인증 팝업 스크립트
•
authIdentity 함수를 호출하여 인증 URL을 가져오고, 해당 URL을 사용하여 본인 인증 팝업창을 띄웁니다.
// IdentityView.vue
<script setup>
async function authIdentity() {
const url = await identityUrl() // 인증 URL을 가져옵니다.
// 본인 인증 팝업창을 띄웁니다.
window.open(
url,
'DRMOKWindow',
'width=425,height=550,scrollbars=no,toolbar=no,location=no,directories=no,status=no'
)
}
</script>
JavaScript
복사
2) API 호출 스크립트
•
identityUrl 함수는 서버에서 본인 인증 URL을 가져오는 API 호출을 수행합니다.
async function identityUrl(isMobile, callbackUrl) {
try {
return await useAxios(
`/identities?isMobile=${isMobile}&callbackUrl=${callbackUrl}`,
{
method: 'POST'
},
apiClient
)
} catch (error) {
console.error('failed to create url', error)
throw error
}
}
JavaScript
복사
나. ‘인증결과 복호화 및 유효성 검사’ 처리
1) 메시지 핸들러 스크립트
•
해당 호스트가 허용된 출처인지 확인한 후, 받아온 본인 인증 결과를 백엔드 서버로 전달합니다.
// IdentityRedirectionView.vue
<script setup>
import { useRoute } from 'vue-router'
import { onMounted } from 'vue'
const route = useRoute()
onMounted(() => {
const priinfo = route.query.priinfo
if (priinfo) {
window.opener.identificationReceived(priinfo)
window.close()
}
})
</script>
JavaScript
복사
// IdentityView.vue
<script setup>
async function identificationReceived(priinfo) {
userStore.userIdentity(priinfo)
}
onMounted(() => {
window.identificationReceived = (data) => {
identificationReceived(data)
}
})
onUnmounted(() => {
delete window.identificationReceived
})
</script>
JavaScript
복사
// userStore.js
export const useUserStore = defineStore('userStore', () => {
const currentUser = useStorage('currentUser', {})
async function userIdentity(encoded) {
const { data } = await authApi.verifyUser(encoded)
currentUser.value.phoneNumber = data.value.phoneNumber
}
return { userIdentity }
})
JavaScript
복사
2) API 호출 스크립트
•
verifyIdentity 함수는 백엔드 서버에서 본인 인증 결과의 복호화 및 유효성 검사를 수행하는 API 호출을 합니다.
async function verifyIdentity(encrypted) {
try {
return await useAxios(
'/identities/verify',
{
method: 'POST',
data: {
data: encrypted
}
},
apiClient
)
} catch (error) {
console.error('failed to verify identity', encrypted, error)
throw error
}
}
JavaScript
복사