NiceOn token 관련수정

This commit is contained in:
jaewohong
2025-12-16 17:55:42 +09:00
parent 037f857a5f
commit 9890f889a4
3 changed files with 300 additions and 3 deletions
@@ -323,7 +323,7 @@ public class HttpClient5AdapterServiceRest extends HttpClient5AdapterServiceSupp
if (useAdapterToken && "AES256-NICEON".equals(encryptAlgorithm)) {
String niceToken = accessToken.getAccessToken();
if ( niceToken == null || niceToken == "") {
throw new Exception("NiceOn Token is empty, toke failed to be issued, TOKEN = [" + niceToken + "]");
throw new Exception("NiceOn Token is empty, TOKEN failed to be issued, TOKEN = [" + niceToken + "]");
}
String clientId = JwtClientIdExtractor(niceToken);
long currentTime = System.currentTimeMillis();
@@ -96,8 +96,7 @@ public class HttpClientAccessTokenServiceWithBase64Header implements HttpClientA
if (!UrlUtils.isAbsoluteUrl(uri)) {
uri = appendPath(adapterUrl, uri);
}
//String contentType = "application/json;"; // comment by jwhong
String contentType = "application/x-www-form-urlencoded"; // 광주은행 나이스지키미
String contentType = "application/json;";
Charset charset;
if (StringUtils.isNotBlank(encode)) {
@@ -0,0 +1,298 @@
package com.eactive.eai.authoutbound.client.impl;
import com.eactive.eai.adapter.AdapterGroupVO;
import com.eactive.eai.adapter.AdapterManager;
import com.eactive.eai.adapter.http.client.HttpClientAdapterServiceKey;
import com.eactive.eai.adapter.http.secure.HttpClient5SSLContextFactory;
import com.eactive.eai.authoutbound.OutboundOAuthCredentialVo;
import com.eactive.eai.authoutbound.client.HttpClientAccessTokenServiceByDB;
import com.eactive.eai.common.util.Logger;
import com.eactive.eai.httpouttlsinfo.HttpOutTlsInfoManager;
import com.eactive.eai.httpouttlsinfo.HttpOutTlsInfoVO;
import com.eactive.eai.util.TestModeChecker;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.openbanking.eai.common.token.AccessTokenVO;
import com.openbanking.eai.common.token.OAuth2AccessTokenVO;
import org.apache.commons.lang3.StringUtils;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
import org.apache.hc.client5.http.ssl.TrustAllStrategy;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.message.BasicNameValuePair;
import org.apache.hc.core5.ssl.SSLContextBuilder;
import org.apache.hc.core5.util.Timeout;
import org.springframework.security.web.util.UrlUtils;
import tcseed.base64;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.*;
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
/**
* 1. 기능 : HTTP 웹 컴포넌트를 POST 방식으로 호출할 수 있는 기능을 제공한다. 2. 처리 개요 : * - 2009.11.24
* retry 로직 제거 : 요청 3. 주의사항
*
* @author :
* @version : v 1.0.0
* @see : WLIAdapterFactory.java, WLIAdapter.java, WLIDefaultAdapter.java
* @since :
*
*/
public class HttpClientAccessTokenServiceWithBase64NiceOn implements HttpClientAccessTokenServiceByDB {
public static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
private static boolean testMode = TestModeChecker.isTestMode();
/**
* 1. 기능 : 법인검증 토큰 발급에 사용 2. 처리 개요 : - 속성 정보를 설정 하고 토큰 발급 URL 호출 한다. 3. 주의사항
* - JSON 방식
* - ( Header Authorization Basic <base64_Encode(client_id:client_secret)> ) 으로 구성
* @param adapterProp Http Adapter 속성 정보
* @return 반환 된 AccessTokenVO
* @exception Exception 수동 시스템 간 통신 중 발생
**/
public AccessTokenVO execute(String name, Properties adapterProp, OutboundOAuthCredentialVo oAuthCredentialVo)
throws Exception {
AdapterGroupVO gvo = AdapterManager.getInstance().getAdapterGroupVO(name);
String adapterUrl = adapterProp.getProperty("URL");
String encode = gvo.getMessageEncode();
String timeoutTemp = adapterProp.getProperty("HTTP_TIME_OUT");
if (StringUtils.isBlank(timeoutTemp)) {
timeoutTemp = "30000";
}
String connectionTimeoutTemp = adapterProp.getProperty("CONNECTION_TIMEOUT");
if (StringUtils.isBlank(connectionTimeoutTemp)) {
connectionTimeoutTemp = "30000";
}
int timeout = Integer.parseInt(timeoutTemp);
int connectionTimeout = Integer.parseInt(connectionTimeoutTemp);
long currentTime = System.currentTimeMillis();
String uri = oAuthCredentialVo.getUrl();
if (!UrlUtils.isAbsoluteUrl(uri)) {
uri = appendPath(adapterUrl, uri);
}
String contentType = "application/x-www-form-urlencoded"; // 광주은행 나이스지키미
Charset charset;
if (StringUtils.isNotBlank(encode)) {
charset = Charset.forName(encode);
} else {
charset = Charset.defaultCharset();
encode = charset.toString();
}
boolean useForwardProxy = StringUtils.equalsIgnoreCase(adapterProp.getProperty("FORWARD_PROXY_USE_YN"), "Y");
String forwardProxyUrl = adapterProp.getProperty("FORWARD_PROXY_URL");
logger.debug(
"uri:{}, charset:{}, transactionTimeout:{}, connectionTimeout:{}, useForwardProxy:{}, forwardProxyUrl:{}",
uri, encode, timeout, connectionTimeout, useForwardProxy, forwardProxyUrl);
List<NameValuePair> formParams = new ArrayList<>();
formParams.add(new BasicNameValuePair("client_id", oAuthCredentialVo.getClientId()));
formParams.add(new BasicNameValuePair("client_secret", oAuthCredentialVo.getClientSecret()));
formParams.add(new BasicNameValuePair("scope", oAuthCredentialVo.getScope()));
formParams.add(new BasicNameValuePair("grant_type", oAuthCredentialVo.getGrantType()));
// mTLS config with default connection parameters
boolean useMtls = StringUtils.equalsIgnoreCase(adapterProp.getProperty(HttpClientAdapterServiceKey.USE_MTLS),
"Y");
AdapterGroupVO adapterGroup = AdapterManager.getInstance().getAdapterGroup(name);
String clientId = adapterGroup.getClientId();
if (logger.isInfo()) {
logger.info("MTLS adapterGroupName. : {}, useMtls. : {}, clientId : {}", name, useMtls, clientId);
}
int maxTotalConnections = HttpClientAdapterServiceKey.DEFAULT_MAX_TOTAL_CONNECTIONS;
int maxHostConnections = HttpClientAdapterServiceKey.DEFAULT_MAX_CONNECTION_PER_HOST;
HttpOutTlsInfoVO mtlsInfo = null;
SSLContext sslContext = null;
PoolingHttpClientConnectionManagerBuilder cmBuilder = PoolingHttpClientConnectionManagerBuilder.create();
PoolingHttpClientConnectionManager connectionManager = null;
try {
if (useMtls) {
HttpOutTlsInfoManager tlsManager = HttpOutTlsInfoManager.getInstance();
if (StringUtils.isNotEmpty(clientId)) {
mtlsInfo = tlsManager.getHttpOutTlsInfo(clientId);
}
}
if (useMtls && mtlsInfo != null) {
String storeType = mtlsInfo.getStoreType();
String keyStoreInfo = mtlsInfo.getKeystoreInfo();
String keyStorePassword = mtlsInfo.getKeystorePassword();
String trustStoreInfo = mtlsInfo.getTruststoreInfo();
String trustStorePassword = mtlsInfo.getTruststorePassword();
String[] tlsVersions = null;
String[] cipherSuites = null;
if (StringUtils.isAnyEmpty(keyStoreInfo, keyStorePassword)) {
throw new Exception("mTLS keyStore config error");
}
boolean skipTrust = false;
if (StringUtils.isAnyEmpty(trustStoreInfo, trustStorePassword)) {
if (logger.isWarn())
logger.warn("Skip trustStore validation adapterGroupName : " + name);
skipTrust = true;
}
sslContext = HttpClient5SSLContextFactory.createMTLSContextFromContent(storeType, keyStoreInfo,
keyStorePassword, trustStoreInfo, trustStorePassword, skipTrust, tlsVersions, cipherSuites);
SSLConnectionSocketFactory sslSocketFactory = null;
if (testMode) {
sslSocketFactory = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
} else {
sslSocketFactory = new SSLConnectionSocketFactory(sslContext);
}
cmBuilder.setSSLSocketFactory(sslSocketFactory);
} else {
sslContext = SSLContextBuilder.create().loadTrustMaterial(new TrustAllStrategy()).build();
SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);
cmBuilder.setSSLSocketFactory(csf);
}
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException | CertificateException
| IOException | UnrecoverableKeyException e) {
throw new RuntimeException(e);
} catch (Exception e) {
throw new RuntimeException(e);
}
connectionManager = cmBuilder.build();
connectionManager.setMaxTotal(maxTotalConnections);
connectionManager.setDefaultMaxPerRoute(maxHostConnections);
try (CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connectionManager).build();) {
HttpPost httpPost = new HttpPost(uri);
httpPost.setEntity(new UrlEncodedFormEntity(formParams, charset));
httpPost.setHeader("Content-Type", contentType+" charset=" + encode);
//HTTP HEADER에 client id, client secret를 base64Encode 한 후 추가
String cId = oAuthCredentialVo.getClientId();
String cSecret = oAuthCredentialVo.getClientSecret();
String authValue = cId + ":" + cSecret;
String encodedAuth = Base64.getEncoder().encodeToString(authValue.getBytes(StandardCharsets.UTF_8));
httpPost.setHeader("Authorization","Basic "+ encodedAuth);
RequestConfig.Builder requestConfigBuilder = RequestConfig.custom();
if (useForwardProxy) {
java.net.URL url = new java.net.URL(forwardProxyUrl);
// 프로토콜, 호스트, 포트 추출
String protocol = url.getProtocol();
String host = url.getHost();
int port = url.getPort();
HttpHost proxy = new HttpHost(protocol, host, port);
requestConfigBuilder.setProxy(proxy);
}
RequestConfig requestConfig = requestConfigBuilder
.setConnectTimeout(Timeout.ofMilliseconds(connectionTimeout))
.setResponseTimeout(Timeout.ofMilliseconds(timeout)).build();
httpPost.setConfig(requestConfig);
logger.debug("uri = [" + uri + "]");
logger.debug("oauthClientId = [" + oAuthCredentialVo.getClientId() + "]");
logger.debug("oauthClientSecret = [" + oAuthCredentialVo.getClientSecret() + "]");
logger.debug("oauthScope = [" + oAuthCredentialVo.getScope() + "]");
logger.debug("oauthGrantType = [" + oAuthCredentialVo.getGrantType() + "]");
logger.debug("oauthauthValue = [" + authValue + "]");
logger.debug("oauthauthEncodedAuth = [" + encodedAuth + "]");
logger.debug("contentType = [" + contentType + "]");
logger.debug("encode = [" + encode + "]");
OAuth2AccessTokenVO accessToken = new OAuth2AccessTokenVO();
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
if (response.getCode() != 200) {
throw new Exception("NiceOn token receive status fail value= " + response.getCode());
}
logger.info("HttpClientAccessTokenServiceWithBase64NiceOn==>" + response.getCode());
HttpEntity entity = response.getEntity();
String responseString = EntityUtils.toString(entity, encode);
logger.debug("Base64NiceOn oauthToken RECV = [" + responseString + "]");
if (StringUtils.isNotBlank(responseString)) {
ObjectMapper objectMapper = new ObjectMapper();
JsonNode responseJSON = objectMapper.readTree(responseString);
if (responseJSON.has("access_token") && responseJSON.has("token_type")
&& responseJSON.has("expires_in") && responseJSON.has("scope")) {
accessToken.setAccessToken(responseJSON.get("access_token").asText());
accessToken.setTokenType(responseJSON.get("token_type").asText());
long expiresIn = responseJSON.get("expires_in").asLong();
accessToken.setExpiration(new Date(currentTime + expiresIn * 1000L));
accessToken.setScope(responseJSON.get("scope").asText());
}
if (responseJSON.has("client_use_code")) {
accessToken.setClientUseCode(responseJSON.get("client_use_code").asText());
}
logger.debug("oauthToken =" + accessToken.toString());
return accessToken;
} else {
throw new Exception("oauth token return null");
}
} catch (Exception e) {
e.printStackTrace();
logger.error("[HttpClientAccessTokenServiceWithBase64NiceOn] retrieve accessToken exception :" + e.getMessage());
return accessToken;
}
}
}
/**
* URL에 경로를 추가합니다. 중복되는 슬래시를 방지합니다.
*
* @param baseUrl 기본 URL
* @param pathToAdd 추가할 경로
* @return 완성된 URL 문자열
*/
public static String appendPath(String baseUrl, String pathToAdd) {
if (!baseUrl.endsWith("/") && !pathToAdd.startsWith("/")) {
return baseUrl + "/" + pathToAdd;
} else if (baseUrl.endsWith("/") && pathToAdd.startsWith("/")) {
return baseUrl + pathToAdd.substring(1);
} else {
return baseUrl + pathToAdd;
}
}
}