KCP 휴대폰 본인인증 컨버팅

현재 회사에서 나온 이슈인데, 하나의 고객이 SNS 로그인을 이용해서 여러개의 계정을 가지고 있어 히스토리가 분산이 되는 이슈가 있었다. 그래서 회사에서 KCP 본인 인증 서비스를 도입하면서 겪은 문제와 해결방법들등을 공유 한다. (더 좋은 방법이 있으면 알려주세요 ㅠㅠ)

문제점

  • 제휴전까지는 참고용으로 알수 있는 문서가 없다.(다른 본인 서비스와 비교를 할수 있는 건더기가 하나도 없어서 그저 운에 기대는 수 밖에 없다.)
  • 제휴후에 문서를 받고나서 확인을 해보니 서버쪽 예제코드는 php밖에 없다. 심지어 대부분의 SNS로그인처럼 쉽게 호출이 어렵고 암호화된 값을 실시간으로 만들어서 kcp쪽에 보내줘야해서 좀 복잡하다.
  • kcp에 보내는 방식도 post로 보내야 해서 리다이렉트를 할 수가 없고 조금 많이 복잡하다.
  • 암호화 할때, 시간관련 고유값이 있어야 하고, 암호화는 kcp에서 제공하는 바이너리 프로그램을 통해서 암호화가 가능하다.
  • 물론 해독도 마찬가지로 kcp에서 제공하는 바이너리 프로그램을 통해서 해독이 가능하다.

해결방안

우선은 회사에 서버개발자들이 전부 Node.js 개발자라 php코드 그대로 가는 부분은 크게 염두에 두지 않았고, node로 컨버팅이 가능한지에 대한 여부를 주로 확인을 했으며, 가능하면 Docker에서 사용이 가능한지도 같이 확인을 했다.

다행이도 메인이 되는 바이너리 파일을 Node.js 에서 child_process 라이브러리를 이용하여 호출이 가능했고, Docker 여부도 node 이미지가 리눅스 기반이라 메인이 되는 바이너리 파일이 동작이 되는것을 확인했다.

작업

우선은 로컬에서 동작이 불가능해서 크게 2개의 환경을 구축하고 작업을 시작했다.

  • 우선은 정상적을 동작이 가능한지 확인 하기위한, ubuntu 기반의 개발 서버에 docker 없이 샘플로 준 php로 돌아가는 서버
  • Docker 의 Node기반의 서버

우선 php서버는 1번서버이고 node기반의 서버는 2번 서버라고 하겠다.

우선 서버에 필요한 페이지는 2개정도 필요하므로 예상이 되서 두개의 페이지를 만들기 시작했다,

  1. 서버로 요청이 오면 바로 kcp에서 요청을 원하는 형식에 맞게 보내는 데이터를 만들고 보내는 페이지
  2. kcp서버에서 본인 인증이 보낸 암호화된 데이터를 다시 복호화를 해서 유저의 데이터를 수정후 성공 여부를 앱에서 알수 있도록 해주는 페이지

요청 페이지

우선 페이지가 간단하고, 유저에게 보여줄 내용이 없는 페이지로 거의 html이 로드 되자마자, 바로 kcp 서버로 요청을 보내기만 하면 되는 페이지다 보니 간단하게 pug템플릿을 통해서 만들수 있다.

1
2
3
4
5
6
7
8
9
10
11
doctype html
html(lang='ko')
head
title Certification
body
form(method='post' action=url)#from
each val, key in body
input(name=key, value=val, type='hidden')
script(type='text/javascript').
document.getElementById('from').submit();

위 와같이 pug파일을 작성하면, 이 페이지가 로드 되자마자 바로 kcp 인증 페이지로 리다이렉트가 된다.

이제 body에 들어가는 값들을 만들어주는데, body값은 pug페이지를 렌더링할때, 인자값에 객체로 보내는 값에 body값을 포함해서 보내면 되며, 대부분의 값은 고정이나, ordr_idxx 값이나 hash_key 값은 실시간으로 만들어 줘야하며, site_cd값은 보안상 환경변수로 사용하다가 같이 넣어줘야 한다. 그리고 Ret_URL값은 환경에 따라서 바뀌는 값이라 환경 변수 처리를 하는게 좋다.

그리고 up_hash를 만드는 방법은 날짜와 시간을 조합해서 고유의 ordr_idxx, kcp에서 재공하는 site_cd, 그리고 16자리의 hash_key값을 이용해서 클라이언트에서 사용하는 hash값을 만들어준다.

이때 위에서 계속 말하는 바이너리 파일은 ct_cli 파일인데 다음과 같이 사용하면 해시값을 만들어 준다.

1
ct_cli lf_CT_CLI__make_hash_data hash_key data 

아 그리고 위에 들어가는 data값은 다음과 같이 조합을 해야한다.

1
data=`${site_cd}${ordr_idxx}${web_siteid}${user_name}${year}${month}${day}${sex_code}${local_code}`

위의 데이터에 들어가는 order_idxx값을 만들때의 시간데이터는 요청시의 시간이고, data에 들어가는 ${user_name}${year}${month}${day}${sex_code}${local_code}값들은 본인 인증을 요청하는 고객의 정보로, 만약 없으면 넣지 않아도 되는 값이라고 보면 된다,
그리고 위의 데이터의 년월일은 포맷이 YYYYMMDD이며, 없는경우 00000000을 넣어주면 된다.

이 API의 난간은 up_hash를 재대로 만들지 못하면 어디에서 잘못됬는지 찾는데 시간이 걸리는데, 이때, 기존의 php서버에 로그를 찍어서 확인하면 그나마 쉽게 추적이 가능하다.

그리고 param_opt 변수를 이용할 때, base64로 인코딩을 해줘야 나중에 Ret_URL을 통해서 값을 받을때, 정상적인 응답값을 내려준다.

응답 페이지

이 페이지는 크게 4가지 동작을 해야하는데, 첫번째로는 kcp에서 보내준 데이터중 암호화된 데이터를 체크하는 동작, 암호화된 데이터를 복호화해서 확인하는 작업, 복호화한 데이터를 기반으로 자사 서비스에서 본인 인증여부를 수정하는 작업, 클라이언트에 실패유무를 알여주는 페이지

우선은 kcp에서 보내준 데이터중 암호화된 데이터를 체크하는 동작은요청페이지 을 완료했다면 크게 문제없이 완성이 가능하다.

문제는 암호화된 데이터를 복호화하는 작업이다. 우선은 테스트서버에서만 그런지는 모르겠는데, 불규칙적으로 -4가나온다. 두번째로는 복호화 한 데이터를 객체형태로 만들기가 조금 귀찮다.

우선 복호화할때 옵션으로 0을 주면 utf-8형식으로 복호화가 되며, 정규식을 이용해서 쿼리 문자열 형식으로 변환후 객체로 변환했다.

우선 utf-8형식으로 나온 값의 형식은 key=value\u001key=value... 와같은데 정규식으로 /\u001f/g이용해서 &으로 변경 후 querystringparse함수를 이용해서 객체로 변환해주면 된다.

이렇게 복호화한 데이터를 가지고 서버측 데이터를 수정해주면 되며, 수정까지 완료가 되면, 응답용 pug페이지를 이용해서 클라이언트에 알려주면된다.

이때 클라이언트 단은 크게 3가지가 있는데 일반 웹, Android, IOS 이렇게 3가지 환경이 있는데 이 모든 환경이 다르게 응답을 내려줘야 한다.

우선 웹에서는 보통 인증을 팝업을 띄어서 작업을 하기 때문에 부모 웹에 성공또는 실패 요청을 날려줘야 하고, Android나 IOS에서는 웹뷰를 띄우기 때문에 Android나 IOS에서 성공또는 실패 이벤트를 받을수 있도록 자바스크립트 이벤트를 날려줘야한다.

Android

1
window.'모바일에서 정의한 변수'.'모바일에서 정의한 이벤트'('이벤트 내용')

위와 같이 이용하면 된다. 참고로 Android에서 객체는 못 받아서 객체를 넘겨줘야하는 경우 JSON.sstringify을 이용하여 객체를 문자열로 컨버팅해서 전달해줘야한다.

IOS

1
window.webkit.messageHandlers.'모바일에서 정의한 이벤트'.postMessage(이벤트 내용)

위와 같이 사용이 가능하며, IOS에서는 객체를 받을수 있으며, 추가적으로는 비어있는 내용으로 함수를 보내는경우 {}이라도 추가를 해줘야 정상적으로 클라이언트에서 받는다.

Web

1
window.opener.postMessage(이벤트 내용,'*')

위와 같이 사용이 가능한데, 위 방식은 웹에서 popup을 이용하여 요청을 하며, 도메인이 다른경우에 cors 문제가 생겨서 위처럼 하였다. 이때, 이벤트 내용으로 민감한 내용은 보내지 않는겻을 추천한다.

2019-2024 sungmun