|
|
|
@ -1,9 +1,11 @@
|
|
|
|
|
package kr.xit.ens.support.nice.service;
|
|
|
|
|
package kr.xit.ens.nice.service;
|
|
|
|
|
|
|
|
|
|
import egovframework.com.cmm.EgovMessageSource;
|
|
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
|
|
import java.security.InvalidKeyException;
|
|
|
|
|
import java.security.KeyFactory;
|
|
|
|
|
import java.security.NoSuchAlgorithmException;
|
|
|
|
|
import java.security.PublicKey;
|
|
|
|
|
import java.security.spec.InvalidKeySpecException;
|
|
|
|
|
import java.security.spec.X509EncodedKeySpec;
|
|
|
|
|
import java.util.Base64;
|
|
|
|
@ -11,7 +13,6 @@ import java.util.Date;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.Random;
|
|
|
|
|
import java.util.Set;
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
import javax.crypto.BadPaddingException;
|
|
|
|
@ -28,17 +29,21 @@ import kr.xit.biz.ens.model.nice.NiceCiDTO.PublickeyResDataBody;
|
|
|
|
|
import kr.xit.biz.ens.model.nice.NiceCiDTO.PublickeyResponse;
|
|
|
|
|
import kr.xit.biz.ens.model.nice.NiceCiDTO.RequestDataHeader;
|
|
|
|
|
import kr.xit.biz.ens.model.nice.NiceCiDTO.ResponseDataHeader;
|
|
|
|
|
import kr.xit.biz.ens.model.nice.NiceCiDTO.SymkeyRegInfo;
|
|
|
|
|
import kr.xit.biz.ens.model.nice.NiceCiDTO.SymmetrickeyRegReqDataBody;
|
|
|
|
|
import kr.xit.biz.ens.model.nice.NiceCiDTO.SymmetrickeyRegRequest;
|
|
|
|
|
import kr.xit.biz.ens.model.nice.NiceCiDTO.SymmetrickeyRegResponse;
|
|
|
|
|
import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenRequest;
|
|
|
|
|
import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenResponse;
|
|
|
|
|
import kr.xit.biz.ens.model.nice.NiceCiDTO.TokenRevokeResponse;
|
|
|
|
|
import kr.xit.core.exception.BizRuntimeException;
|
|
|
|
|
import kr.xit.core.spring.annotation.TraceLogging;
|
|
|
|
|
import kr.xit.core.spring.util.ApiWebClientUtil;
|
|
|
|
|
import kr.xit.core.support.utils.DateUtils;
|
|
|
|
|
import kr.xit.core.support.utils.JsonUtils;
|
|
|
|
|
import kr.xit.ens.support.cmm.mapper.ICmmEnsMapper;
|
|
|
|
|
import kr.xit.ens.support.cmm.service.CmmEnsCacheService;
|
|
|
|
|
import kr.xit.core.support.utils.UUIDGenerateUtils;
|
|
|
|
|
import kr.xit.ens.cmm.mapper.ICmmEnsMapper;
|
|
|
|
|
import kr.xit.ens.cmm.service.CmmEnsCacheService;
|
|
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import org.apache.commons.lang3.ObjectUtils;
|
|
|
|
@ -55,7 +60,7 @@ import org.springframework.util.Base64Utils;
|
|
|
|
|
* <pre>
|
|
|
|
|
* description :
|
|
|
|
|
*
|
|
|
|
|
* packageName : kr.xit.ens.support.nice.service
|
|
|
|
|
* packageName : kr.xit.ens.nice.service
|
|
|
|
|
* fileName : NiceCiService
|
|
|
|
|
* author : limju
|
|
|
|
|
* date : 2023-09-06
|
|
|
|
@ -92,12 +97,15 @@ public class NiceCiService extends EgovAbstractServiceImpl implements INiceCiSer
|
|
|
|
|
private String API_CI;
|
|
|
|
|
|
|
|
|
|
//FIXME::업무처리 최대 주기
|
|
|
|
|
private final int EXPIRED_CHECK_DAYS = 1;
|
|
|
|
|
private final int EXPIRED_CHECK_DAYS = 0;
|
|
|
|
|
|
|
|
|
|
private static final String AUTH_TYPE_BASIC = "Basic";
|
|
|
|
|
private static final String AUTH_TYPE_BEARER = "bearer";
|
|
|
|
|
private static final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
|
|
|
|
|
private static final String CNTY_CD = "kr";
|
|
|
|
|
private static final String TRAN_ID_PREFIX = "TRAN_ID-";
|
|
|
|
|
|
|
|
|
|
private static final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
|
|
|
|
|
private final EgovMessageSource messageSource;
|
|
|
|
|
private final ApiWebClientUtil webClient;
|
|
|
|
|
private final CmmEnsCacheService cacheService;
|
|
|
|
|
private final ICmmEnsMapper cmmEnsMapper;
|
|
|
|
@ -117,10 +125,12 @@ public class NiceCiService extends EgovAbstractServiceImpl implements INiceCiSer
|
|
|
|
|
public TokenResponse generateToken(final TokenRequest reqDTO){
|
|
|
|
|
validate(reqDTO);
|
|
|
|
|
|
|
|
|
|
CrtfInfo niceDTO = getNiceCrtInfo();
|
|
|
|
|
|
|
|
|
|
Map<String,String> map = new HashMap<>();
|
|
|
|
|
map.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
|
|
|
|
|
map.put(HttpHeaders.AUTHORIZATION,
|
|
|
|
|
String.format("%s %s", AUTH_TYPE_BASIC, Base64Utils.encodeToString(Base64Utils.encode(String.format("%s:%s", this.CLIENT_ID, "this.CLIENT_SECRET").getBytes(StandardCharsets.UTF_8)))));
|
|
|
|
|
String.format("%s %s", AUTH_TYPE_BASIC, Base64Utils.encodeToString(Base64Utils.encode(String.format("%s:%s", CLIENT_ID, niceDTO.getClientSecret()).getBytes(StandardCharsets.UTF_8)))));
|
|
|
|
|
|
|
|
|
|
return webClient.exchange(HOST + API_GENERATE_TOKEN, HttpMethod.POST, JsonUtils.toJson(reqDTO), TokenResponse.class, map);
|
|
|
|
|
}
|
|
|
|
@ -138,15 +148,15 @@ public class NiceCiService extends EgovAbstractServiceImpl implements INiceCiSer
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
@TraceLogging
|
|
|
|
|
public TokenResponse revokeToken(){
|
|
|
|
|
//validate(reqDTO, null);
|
|
|
|
|
public TokenRevokeResponse revokeToken(){
|
|
|
|
|
CrtfInfo niceDTO = getNiceCrtInfo();
|
|
|
|
|
|
|
|
|
|
return webClient.exchange(
|
|
|
|
|
HOST + API_GENERATE_TOKEN,
|
|
|
|
|
HttpMethod.POST,
|
|
|
|
|
null,
|
|
|
|
|
TokenResponse.class,
|
|
|
|
|
getHeaderMap(MediaType.APPLICATION_FORM_URLENCODED_VALUE, AUTH_TYPE_BASIC));
|
|
|
|
|
TokenRevokeResponse.class,
|
|
|
|
|
getHeaderMap(MediaType.APPLICATION_FORM_URLENCODED_VALUE, AUTH_TYPE_BASIC, niceDTO.getAccessToken()));
|
|
|
|
|
}
|
|
|
|
|
//--------------------------------------------------------------------------------
|
|
|
|
|
// 기관용 Token
|
|
|
|
@ -158,15 +168,27 @@ public class NiceCiService extends EgovAbstractServiceImpl implements INiceCiSer
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
@TraceLogging
|
|
|
|
|
public PublickeyResponse requestPublickey(final PublickeyRequest reqDTO) {
|
|
|
|
|
validate(reqDTO);
|
|
|
|
|
public PublickeyResponse requestPublickey() {
|
|
|
|
|
CrtfInfo niceDTO = getNiceCrtInfo();
|
|
|
|
|
|
|
|
|
|
final String todayDt = DateUtils.getTodayAndNowTime("yyyyMMddHHmmss");
|
|
|
|
|
final PublickeyRequest pubReqDTO = PublickeyRequest.builder()
|
|
|
|
|
.dataHeader(RequestDataHeader.builder()
|
|
|
|
|
.cntyId(CNTY_CD)
|
|
|
|
|
.tranId(String.format("%s%s", TRAN_ID_PREFIX, todayDt))
|
|
|
|
|
.build())
|
|
|
|
|
.dataBody(PublickeyReqDataBody.builder()
|
|
|
|
|
.reqDtim(todayDt)
|
|
|
|
|
.build())
|
|
|
|
|
.build();
|
|
|
|
|
validate(pubReqDTO);
|
|
|
|
|
|
|
|
|
|
return webClient.exchange(
|
|
|
|
|
HOST + API_GENERATE_TOKEN,
|
|
|
|
|
HttpMethod.POST,
|
|
|
|
|
null,
|
|
|
|
|
PublickeyResponse.class,
|
|
|
|
|
getHeaderMap(MediaType.APPLICATION_JSON_VALUE, AUTH_TYPE_BEARER));
|
|
|
|
|
getHeaderMap(MediaType.APPLICATION_JSON_VALUE, AUTH_TYPE_BEARER, niceDTO.getAccessToken()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------
|
|
|
|
@ -188,49 +210,91 @@ public class NiceCiService extends EgovAbstractServiceImpl implements INiceCiSer
|
|
|
|
|
* </pre>
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public SymmetrickeyRegResponse requestRegSymmetrickey(SymmetrickeyRegRequest reqDTO) {
|
|
|
|
|
public SymmetrickeyRegResponse requestRegSymmetrickey() {
|
|
|
|
|
//FIXME::NICE 연계이후 메소드 교체
|
|
|
|
|
//CrtfInfo niceDTO = getPublickeyCrtInfo();
|
|
|
|
|
CrtfInfo niceDTO = getNiceCrtInfo();
|
|
|
|
|
|
|
|
|
|
SymkeyRegInfo symkeyRegInfo = getSymkeyRegInfo(niceDTO);
|
|
|
|
|
|
|
|
|
|
//FIXME::NICE 연계이후 comment 제거
|
|
|
|
|
//String encSymkeyRegInfo = encodeString(niceDTO.getPublicKey(), JsonUtils.toJson(symkeyRegInfo));
|
|
|
|
|
String encSymkeyRegInfo = "encodeStringniceDTOgetPublicKeyJsonUtilstoJsonsymkeyRegInfo";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
final String todayDt = DateUtils.getTodayAndNowTime("yyyyMMddHHmmss");
|
|
|
|
|
|
|
|
|
|
SymmetrickeyRegRequest reqDTO = SymmetrickeyRegRequest.builder()
|
|
|
|
|
.dataHeader(RequestDataHeader.builder()
|
|
|
|
|
.cntyId(CNTY_CD)
|
|
|
|
|
.tranId(TRAN_ID_PREFIX + todayDt)
|
|
|
|
|
.build())
|
|
|
|
|
.dataBody(SymmetrickeyRegReqDataBody.builder()
|
|
|
|
|
.pubkeyVersion(niceDTO.getKeyVersion())
|
|
|
|
|
.symkeyRegInfo(encSymkeyRegInfo)
|
|
|
|
|
.build())
|
|
|
|
|
.build();
|
|
|
|
|
validate(reqDTO);
|
|
|
|
|
|
|
|
|
|
Map<String,String> headerMap = getHeaderMap(MediaType.APPLICATION_JSON_VALUE, AUTH_TYPE_BEARER, niceDTO.getAccessToken());
|
|
|
|
|
headerMap.put("ProductID", niceDTO.getProductId());
|
|
|
|
|
|
|
|
|
|
CrtfInfo crtfInfo = getNiceCrtInfo(reqDTO.getDataHeader());
|
|
|
|
|
return webClient.exchange(
|
|
|
|
|
HOST + API_SYMMETRICKEY,
|
|
|
|
|
HttpMethod.POST,
|
|
|
|
|
reqDTO,
|
|
|
|
|
SymmetrickeyRegResponse.class,
|
|
|
|
|
headerMap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------
|
|
|
|
|
// 대칭키 : symmetrickey
|
|
|
|
|
//--------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------------
|
|
|
|
|
/**
|
|
|
|
|
* Nice 인증 정보 조회
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
private CrtfInfo getNiceCrtInfo() {
|
|
|
|
|
CrtfInfo crtfInfo = cacheService.getNiceCrtfInfoCache(SIGNGU_CODE, FFNLG_CODE, CLIENT_ID);
|
|
|
|
|
if(ObjectUtils.isEmpty(crtfInfo)) throw BizRuntimeException.create(messageSource.getMessage("fail.api.nice.crtfInfo"));
|
|
|
|
|
cacheService.logCache();
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
return crtfInfo;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* <pre>
|
|
|
|
|
* 공개키 정보 조회
|
|
|
|
|
* 0. cache call
|
|
|
|
|
* --> 공개키 잔여일 수가 5보다 작으면
|
|
|
|
|
* 1. 공개키 재발급후 공개키 정보 update
|
|
|
|
|
* 2. cache 삭제 && cache call
|
|
|
|
|
* @param reqHeader RequestDataHeader
|
|
|
|
|
* --> 공개키 잔여일 기준 보다 작으면
|
|
|
|
|
* 1. 토큰 폐기
|
|
|
|
|
* 2. 공개키 재발급후
|
|
|
|
|
* 3. 공개키 정보 update
|
|
|
|
|
* 4. cache 삭제 && cache reload
|
|
|
|
|
* @return
|
|
|
|
|
* </pre>
|
|
|
|
|
*/
|
|
|
|
|
private CrtfInfo getNiceCrtInfo(RequestDataHeader reqHeader) {
|
|
|
|
|
CrtfInfo crtfInfo = cacheService.getNiceCrtfInfoCache(SIGNGU_CODE, FFNLG_CODE, CLIENT_ID);
|
|
|
|
|
cacheService.logCache();
|
|
|
|
|
|
|
|
|
|
private CrtfInfo getPublickeyCrtInfo() {
|
|
|
|
|
CrtfInfo crtfInfo = getNiceCrtInfo();
|
|
|
|
|
if(crtfInfo.getRemainingDays() > EXPIRED_CHECK_DAYS) return crtfInfo;
|
|
|
|
|
|
|
|
|
|
//FIXME::공개키 발급요청 call
|
|
|
|
|
PublickeyRequest pubReqDTO = PublickeyRequest.builder()
|
|
|
|
|
.dataHeader(reqHeader)
|
|
|
|
|
.dataBody(PublickeyReqDataBody.builder()
|
|
|
|
|
.reqDtim(DateUtils.getTodayAndNowTime("yyyyMMddHHmmss"))
|
|
|
|
|
.build())
|
|
|
|
|
.build();
|
|
|
|
|
// 1. 토큰 폐기
|
|
|
|
|
TokenRevokeResponse revokeResDTO = revokeToken();
|
|
|
|
|
if(!(revokeResDTO.getDataHeader().getGwRsltCd().equals("1200") && revokeResDTO.getDataBody().isResult())){
|
|
|
|
|
throw BizRuntimeException.create(messageSource.getMessage("fail.api.nice.revoke.token"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PublickeyResponse pubResDTO = requestPublickey(pubReqDTO);
|
|
|
|
|
//PublickeyResponse pubResDTO = JsonUtils.toObject(pubResJson, PublickeyResponse.class);
|
|
|
|
|
// 2. 공개키 발급 요청
|
|
|
|
|
PublickeyResponse pubResDTO = requestPublickey();
|
|
|
|
|
|
|
|
|
|
//FIXME::공개키 정보 갱신
|
|
|
|
|
//FIXME::공개키 정보 갱신 - Error code enum 전환
|
|
|
|
|
ResponseDataHeader dataHeader = pubResDTO.getDataHeader();
|
|
|
|
|
PublickeyResDataBody dataBody = pubResDTO.getDataBody();
|
|
|
|
|
// 3. 공개키 정보 update
|
|
|
|
|
if(dataHeader.getGwRsltCd().equals("1200")
|
|
|
|
|
&& dataBody.getRspCd().equals("P000")
|
|
|
|
|
&& dataBody.getResultCd().equals("0000")){
|
|
|
|
@ -244,16 +308,29 @@ public class NiceCiService extends EgovAbstractServiceImpl implements INiceCiSer
|
|
|
|
|
throw BizRuntimeException.create(JsonUtils.toJson(dataHeader));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4. cache 삭제 && cache reload
|
|
|
|
|
cacheService.removeNiceCrtfInfoCache(SIGNGU_CODE, FFNLG_CODE, CLIENT_ID);
|
|
|
|
|
return cacheService.getNiceCrtfInfoCache(SIGNGU_CODE, FFNLG_CODE, CLIENT_ID);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------------
|
|
|
|
|
// 대칭키 : symmetrickey
|
|
|
|
|
//--------------------------------------------------------------------------------
|
|
|
|
|
/**
|
|
|
|
|
* <pre>
|
|
|
|
|
* 대칭키(symmetrickey) 등록 요청시 symkey_reg_info JSON 데이타 생성
|
|
|
|
|
* @param crtfInfo
|
|
|
|
|
* @return
|
|
|
|
|
* </pre>
|
|
|
|
|
*/
|
|
|
|
|
private SymkeyRegInfo getSymkeyRegInfo(CrtfInfo crtfInfo) {
|
|
|
|
|
return SymkeyRegInfo.builder()
|
|
|
|
|
.siteCode(crtfInfo.getSiteCode())
|
|
|
|
|
.requestNo(UUIDGenerateUtils.generateLengthUuid(30))
|
|
|
|
|
.key(UUIDGenerateUtils.generateLengthUuid(32))
|
|
|
|
|
.iv(UUIDGenerateUtils.generateLengthUuid(16))
|
|
|
|
|
.hmacKey(UUIDGenerateUtils.generateLengthUuid(32))
|
|
|
|
|
.build();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------------
|
|
|
|
|
private Map<String,String> getHeaderMap(final String contentType, final String type){
|
|
|
|
|
private Map<String,String> getHeaderMap(final String contentType, final String type, final String accessToken){
|
|
|
|
|
Map<String,String> map = new HashMap<>();
|
|
|
|
|
if(ObjectUtils.isNotEmpty(contentType)) map.put(HttpHeaders.CONTENT_TYPE, contentType);
|
|
|
|
|
map.put(
|
|
|
|
@ -263,7 +340,7 @@ public class NiceCiService extends EgovAbstractServiceImpl implements INiceCiSer
|
|
|
|
|
Base64Utils.encodeToString(
|
|
|
|
|
Base64Utils.encode(
|
|
|
|
|
String.format("%s:%s:%s",
|
|
|
|
|
"accessToken",
|
|
|
|
|
accessToken,
|
|
|
|
|
(new Date().getTime() / 1000),
|
|
|
|
|
this.CLIENT_ID).getBytes(StandardCharsets.UTF_8))
|
|
|
|
|
)
|
|
|
|
@ -295,13 +372,12 @@ public class NiceCiService extends EgovAbstractServiceImpl implements INiceCiSer
|
|
|
|
|
* @param planText
|
|
|
|
|
* @return
|
|
|
|
|
*/
|
|
|
|
|
protected final String encodeString(final String strPublicKey, final String planText) { //throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
|
|
|
|
|
|
|
|
|
|
private String encodeString(final String strPublicKey, String planText) { //throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
|
|
|
|
|
try {
|
|
|
|
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
|
|
|
|
byte[] cipherEnc = Base64.getDecoder().decode(strPublicKey);
|
|
|
|
|
X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(cipherEnc);
|
|
|
|
|
java.security.PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
|
|
|
|
|
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
|
|
|
|
|
|
|
|
|
|
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
|
|
|
|
|
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
|
|
|
@ -317,16 +393,21 @@ public class NiceCiService extends EgovAbstractServiceImpl implements INiceCiSer
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected final String randomAlphaWord(int wordLength) {
|
|
|
|
|
Random r = new Random();
|
|
|
|
|
|
|
|
|
|
StringBuilder sb = new StringBuilder(wordLength);
|
|
|
|
|
for (int i = 0; i < wordLength; i++) {
|
|
|
|
|
char tmp = (char) ('a' + r.nextInt('z' - 'a'));
|
|
|
|
|
sb.append(tmp);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
return sb.toString();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
// private String encodeString2(final String strPublicKey, final String planText) { //throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
|
|
|
|
|
//
|
|
|
|
|
// try {
|
|
|
|
|
// PublicKey publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAJJxwIDAQAB";
|
|
|
|
|
// Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
|
|
|
|
|
// cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
|
|
|
|
// byte[] bytePlain = cipher.doFinal(planText.getBytes());
|
|
|
|
|
// return Base64Utils.encodeToString(bytePlain);
|
|
|
|
|
//
|
|
|
|
|
// } catch (NoSuchAlgorithmException|InvalidKeySpecException|NoSuchPaddingException|InvalidKeyException e){
|
|
|
|
|
// throw BizRuntimeException.create(e.getMessage());
|
|
|
|
|
// } catch (IllegalBlockSizeException e) {
|
|
|
|
|
// throw BizRuntimeException.create(e.getMessage());
|
|
|
|
|
// } catch (BadPaddingException e) {
|
|
|
|
|
// throw BizRuntimeException.create(e.getMessage());
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
}
|