From 0568edb992d001ed33427f636f54c22d6223c89f Mon Sep 17 00:00:00 2001 From: Rinjae Date: Tue, 16 Sep 2025 18:40:31 +0900 Subject: [PATCH 01/21] =?UTF-8?q?jenkins,=20weblogic=20=EB=8C=80=EC=9D=91?= =?UTF-8?q?=20=EC=9E=91=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 78 ++++++++++++++++++++--------------------- kjb-docs/Jenkinsfile | 83 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 39 deletions(-) create mode 100644 kjb-docs/Jenkinsfile diff --git a/build.gradle b/build.gradle index fbbc1cc..eb7396e 100644 --- a/build.gradle +++ b/build.gradle @@ -64,52 +64,52 @@ dependencies { // implementation ('com.eactive:elink-online-transformer:4.5-SNAPSHOT') { changing = true } // implementation ('com.eactive:elink-online-common:4.5-SNAPSHOT') { changing = true } // implementation ('com.eactive:elink-online-emsclient:4.5-SNAPSHOT') { changing = true } - implementation project(':elink-online-core') - implementation project(':elink-online-transformer') - implementation project(':elink-online-common') - implementation project(':elink-online-emsclient') + implementation project(':elink-online-core') + implementation project(':elink-online-transformer') + implementation project(':elink-online-common') + implementation project(':elink-online-emsclient') - implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation fileTree(dir: 'libs', include: ['*.jar']) // implementation 'org.xerial:sqlite-jdbc:3.39.2.1' - /* - mina-filter-ssl에 Exclude 설정을 하였으나 - mina-integration-spring에서도 mina-filter-ssl을 참조하여 - 해당 "mina-filter-ssl" 참조관계로 인해 ".apache.mina:mina-core:1.0.10"가 참조되는 일이 발생하여 - 두 라이브러르 모두 "exclude group" 설정을 추가함 - 아래의 configurations 처럼 ALL로 제거하여도 무방함 참고 - configurations { - all*.exclude group: 'org.apache.mina', module:'mina-core' - } - */ - implementation ("org.apache.mina:mina-filter-ssl:1.0.10"){ - exclude group: 'org.apache.mina' - } - implementation ('org.apache.mina:mina-integration-spring:1.0.10'){ - exclude group: 'org.apache.mina' - } + /* + mina-filter-ssl에 Exclude 설정을 하였으나 + mina-integration-spring에서도 mina-filter-ssl을 참조하여 + 해당 "mina-filter-ssl" 참조관계로 인해 ".apache.mina:mina-core:1.0.10"가 참조되는 일이 발생하여 + 두 라이브러르 모두 "exclude group" 설정을 추가함 + 아래의 configurations 처럼 ALL로 제거하여도 무방함 참고 + configurations { + all*.exclude group: 'org.apache.mina', module:'mina-core' + } + */ + implementation ("org.apache.mina:mina-filter-ssl:1.0.10"){ + exclude group: 'org.apache.mina' + } + implementation ('org.apache.mina:mina-integration-spring:1.0.10'){ + exclude group: 'org.apache.mina' + } - //implementation 'com.eactive:java_websocket-custom:1.0' - - //implementation "tmax:webt:7.0.2.0-r11661-forJEUS8.0" - //implementation "tmax:webtasync:2.0.3.1-r11801-forJEUS8.1" + //implementation 'com.eactive:java_websocket-custom:1.0' + + //implementation "tmax:webt:7.0.2.0-r11661-forJEUS8.0" + //implementation "tmax:webtasync:2.0.3.1-r11801-forJEUS8.1" - implementation 'org.graylog2:gelfj:1.1.16' + implementation 'org.graylog2:gelfj:1.1.16' - implementation "org.springframework:spring-webmvc:${springVersion}" - implementation "org.springframework.security:spring-security-jwt:1.1.1.RELEASE" + implementation "org.springframework:spring-webmvc:${springVersion}" + implementation "org.springframework.security:spring-security-jwt:1.1.1.RELEASE" - //implementation "com.eactive:ojdbc8:1.0" - //implementation "org.postgresql:postgresql:42.2.23" + //implementation "com.eactive:ojdbc8:1.0" + //implementation "org.postgresql:postgresql:42.2.23" implementation 'org.mariadb.jdbc:mariadb-java-client:2.7.4' //implementation "com.oracle.ojdbc:ojdbc8:19.3.0.0" - implementation 'org.slf4j:jul-to-slf4j:1.7.35' - implementation 'org.slf4j:jcl-over-slf4j:1.7.35' - implementation 'org.slf4j:log4j-over-slf4j:1.7.35' - implementation 'org.slf4j:slf4j-api:1.7.35' + implementation 'org.slf4j:jul-to-slf4j:1.7.35' + implementation 'org.slf4j:jcl-over-slf4j:1.7.35' + implementation 'org.slf4j:log4j-over-slf4j:1.7.35' + implementation 'org.slf4j:slf4j-api:1.7.35' implementation 'co.elastic.logging:logback-ecs-encoder:1.5.0' implementation 'net.sf.j8583:j8583:1.18.0' @@ -149,11 +149,11 @@ configurations.all { } task settingEclipseEncoding { - if (project.file('.settings').exists()) { - File f = file('.settings/org.eclipse.core.resources.prefs') - f.write('eclipse.preferences.version=1\n') - f.append('encoding/=utf-8') - } + if (project.file('.settings').exists()) { + File f = file('.settings/org.eclipse.core.resources.prefs') + f.write('eclipse.preferences.version=1\n') + f.append('encoding/=utf-8') + } } //eclipseJdt.finalizedBy settingEclipseEncoding diff --git a/kjb-docs/Jenkinsfile b/kjb-docs/Jenkinsfile new file mode 100644 index 0000000..65f3f1b --- /dev/null +++ b/kjb-docs/Jenkinsfile @@ -0,0 +1,83 @@ +pipeline { + agent { label 'apipod01' } + + environment { + // Java 환경 설정 + JAVA_HOME = '/App/jenkins/jdks/jdk1.8.0_441' + PATH = "${JAVA_HOME}/bin:${env.PATH}" + + // Gradle 환경 설정 + GRADLE_HOME = '/App/jenkins/gradle-8.7' + GRADLE_USER_HOME = '/App/jenkins/gradle-home' + // GRADLE_OPTS = '--offline' + + // Git 저장소 정보 + GIT_SERVER = '192.168.240.178:18081' + GIT_CREDENTIALS_ID = 'git-ssh-credentials' + + // 프로젝트 디렉토리 구조 + PROJECT_HOME = '/Data/jenkins/eapim' + + BRANCH = 'staging' + } + + + stages { + stage('Git pull') { + steps { + echo "[online] Git pull from branch: ${BRANCH}" + dir("${PROJECT_HOME}/eapim-online") { + git url: "ssh://git@${GIT_SERVER}/eapim/eapim-online", branch: "${BRANCH}", credentialsId: "${GIT_CREDENTIALS_ID}" + } + + echo "[online-core] Git pull from branch: ${BRANCH}" + dir("${PROJECT_HOME}/eapim-online/elink-online-core") { + git url: "ssh://git@${GIT_SERVER}/eapim/elink-online-core", branch: "${BRANCH}", credentialsId: "${GIT_CREDENTIALS_ID}" + } + + echo "[online-core-jpa] Git pull from branch: ${BRANCH}" + dir("${PROJECT_HOME}/eapim-online/elink-online-core-jpa") { + git url: "ssh://git@${GIT_SERVER}/eapim/elink-online-core-jpa", branch: "${BRANCH}", credentialsId: "${GIT_CREDENTIALS_ID}" + } + + + echo "[online-transformer] Git pull from branch: ${BRANCH}" + dir("${PROJECT_HOME}/eapim-online/elink-online-transformer") { + git url: "ssh://git@${GIT_SERVER}/eapim/elink-online-transformer", branch: "${BRANCH}", credentialsId: "${GIT_CREDENTIALS_ID}" + } + + echo "[online-common] Git pull from branch: ${BRANCH}" + dir("${PROJECT_HOME}/eapim-online/elink-online-common") { + git url: "ssh://git@${GIT_SERVER}/eapim/elink-online-common", branch: "${BRANCH}", credentialsId: "${GIT_CREDENTIALS_ID}" + } + + echo "[online-emsclient] Git pull from branch: ${BRANCH}" + dir("${PROJECT_HOME}/eapim-online/elink-online-emsclient") { + git url: "ssh://git@${GIT_SERVER}/eapim/elink-online-emsclient", branch: "${BRANCH}", credentialsId: "${GIT_CREDENTIALS_ID}" + } + } + } + + + stage('Build') { + steps { + tool name: 'Oracle-JDK-1.8', type: 'hudson.model.JDK' + + echo "[admin] Build project" + dir("${PROJECT_HOME}/eapim-online") { + sh '${GRADLE_HOME}/bin/gradle clean build -x test -Pprofile=weblogic' + } + } + } + + + stage('Archive WAR') { + steps { + echo "[admin] Archive WAR file" + dir("${PROJECT_HOME}/eapim-admin/build/libs") { + archiveArtifacts artifacts: '*.war', fingerprint: true + } + } + } + } +} \ No newline at end of file From d120e96f7ca37ce2ec31bb29a4012099b3b12cd8 Mon Sep 17 00:00:00 2001 From: Rinjae Date: Wed, 17 Sep 2025 16:26:08 +0900 Subject: [PATCH 02/21] =?UTF-8?q?weblogic=20=EB=8C=80=EC=9D=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- WebContent/WEB-INF/weblogic-web.xml | 158 ++++++++++++++++++++++++++++ WebContent/WEB-INF/weblogic.xml | 29 +++-- 2 files changed, 180 insertions(+), 7 deletions(-) create mode 100644 WebContent/WEB-INF/weblogic-web.xml diff --git a/WebContent/WEB-INF/weblogic-web.xml b/WebContent/WEB-INF/weblogic-web.xml new file mode 100644 index 0000000..3e0192a --- /dev/null +++ b/WebContent/WEB-INF/weblogic-web.xml @@ -0,0 +1,158 @@ + + + + + ONLWeb + + FrontFilter + com.eactive.eai.admin.FrontFilter + + + FrontFilter + /HTT/* + /WebAgent/* + /adapter/* + /agent/* + /common/* + /management/* + /mgr/* + + + + logbackDisableServletContainerInitializer + true + + + + org.springframework.web.context.ContextLoaderListener + + + contextConfigLocation + /WEB-INF/applicationContext.xml + + + + + authserver + org.springframework.web.servlet.DispatcherServlet + 1 + + + authserver + / + + + + springSecurityFilterChain + org.springframework.web.filter.DelegatingFilterProxy + + contextAttribute + org.springframework.web.servlet.FrameworkServlet.CONTEXT.authserver + + + + springSecurityFilterChain + /* + + + + + + + + + + + + + + + + + + + + + + + WebAgent + com.eactive.eai.agent.web.WebAgent + + + WebAgent + /WebAgent + + + + + Dynamic + com.eactive.eai.adapter.http.dynamic.HttpAdapterMain + + + Dynamic + /HTT/* + + + + index.jsp + + + 500 + /error.jsp + + + \ No newline at end of file diff --git a/WebContent/WEB-INF/weblogic.xml b/WebContent/WEB-INF/weblogic.xml index 73564f6..5779a45 100644 --- a/WebContent/WEB-INF/weblogic.xml +++ b/WebContent/WEB-INF/weblogic.xml @@ -1,9 +1,24 @@ - - / - - 1800 - JSESSIONID_ONL - replicated_if_clustered - + + + monitoring + + 1800 + JSESSIONID_EMS + replicated_if_clustered + + + + + org.slf4j.* + ch.qos.logback.* + + + org/slf4j/impl/StaticLoggerBinder.class + + + \ No newline at end of file From 6d2faf3d16ad64ee9e101ec327b032d75687ca8a Mon Sep 17 00:00:00 2001 From: Rinjae Date: Wed, 1 Oct 2025 22:09:40 +0900 Subject: [PATCH 03/21] jenkinsfile update --- WebContent/WEB-INF/weblogic.xml | 7 ++----- kjb-docs/Jenkinsfile | 17 ++++++++++++----- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/WebContent/WEB-INF/weblogic.xml b/WebContent/WEB-INF/weblogic.xml index 5779a45..88a6c5f 100644 --- a/WebContent/WEB-INF/weblogic.xml +++ b/WebContent/WEB-INF/weblogic.xml @@ -1,10 +1,7 @@ - + - monitoring + / 1800 JSESSIONID_EMS diff --git a/kjb-docs/Jenkinsfile b/kjb-docs/Jenkinsfile index 65f3f1b..cf12b2c 100644 --- a/kjb-docs/Jenkinsfile +++ b/kjb-docs/Jenkinsfile @@ -1,4 +1,6 @@ pipeline { + // agent { label 'apigwd01' } + // 노트북망에서는 apipod01 서버에서 진행한다. agent { label 'apipod01' } environment { @@ -18,7 +20,7 @@ pipeline { // 프로젝트 디렉토리 구조 PROJECT_HOME = '/Data/jenkins/eapim' - BRANCH = 'staging' + BRANCH = 'jenkins_with_weblogic' } @@ -30,7 +32,7 @@ pipeline { git url: "ssh://git@${GIT_SERVER}/eapim/eapim-online", branch: "${BRANCH}", credentialsId: "${GIT_CREDENTIALS_ID}" } - echo "[online-core] Git pull from branch: ${BRANCH}" + echo "[online-core] Git pull from branch: ${BRANCH}" dir("${PROJECT_HOME}/eapim-online/elink-online-core") { git url: "ssh://git@${GIT_SERVER}/eapim/elink-online-core", branch: "${BRANCH}", credentialsId: "${GIT_CREDENTIALS_ID}" } @@ -46,15 +48,20 @@ pipeline { git url: "ssh://git@${GIT_SERVER}/eapim/elink-online-transformer", branch: "${BRANCH}", credentialsId: "${GIT_CREDENTIALS_ID}" } - echo "[online-common] Git pull from branch: ${BRANCH}" + echo "[online-common] Git pull from branch: ${BRANCH}" dir("${PROJECT_HOME}/eapim-online/elink-online-common") { git url: "ssh://git@${GIT_SERVER}/eapim/elink-online-common", branch: "${BRANCH}", credentialsId: "${GIT_CREDENTIALS_ID}" } - echo "[online-emsclient] Git pull from branch: ${BRANCH}" + echo "[online-emsclient] Git pull from branch: ${BRANCH}" dir("${PROJECT_HOME}/eapim-online/elink-online-emsclient") { git url: "ssh://git@${GIT_SERVER}/eapim/elink-online-emsclient", branch: "${BRANCH}", credentialsId: "${GIT_CREDENTIALS_ID}" } + + echo "[kjb-safedb] Git pull from branch: ${BRANCH}" + dir("${PROJECT_HOME}/kjb-safedb") { + git url: "ssh://git@${GIT_SERVER}/eapim/kjb-safedb", branch: "${BRANCH}", credentialsId: "${GIT_CREDENTIALS_ID}" + } } } @@ -74,7 +81,7 @@ pipeline { stage('Archive WAR') { steps { echo "[admin] Archive WAR file" - dir("${PROJECT_HOME}/eapim-admin/build/libs") { + dir("${PROJECT_HOME}/eapim-online/build/libs") { archiveArtifacts artifacts: '*.war', fingerprint: true } } From a02d179ba18f02925928da1844c154d534371d6d Mon Sep 17 00:00:00 2001 From: jaewohong Date: Mon, 13 Oct 2025 14:05:47 +0900 Subject: [PATCH 04/21] =?UTF-8?q?KJBank=20=EC=95=94=ED=98=B8=ED=99=94=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EB=B0=8F=20Sync=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WEB-INF/properties/env.common.properties | 4 +- .../adapter/service/ApiAdapterService.java | 167 +++++++++++++++++- 2 files changed, 167 insertions(+), 4 deletions(-) diff --git a/WebContent/WEB-INF/properties/env.common.properties b/WebContent/WEB-INF/properties/env.common.properties index 1341574..9122d87 100644 --- a/WebContent/WEB-INF/properties/env.common.properties +++ b/WebContent/WEB-INF/properties/env.common.properties @@ -18,7 +18,9 @@ shutdown.wait.intervalms=1000 # message function # use default options # async queue -use.internal.queue=true +// below false to test Weblogic JMS, jwhong +#use.internal.queue=true +use.internal.queue=false # sync-async mapping use.internal.topic=true # restore mapping diff --git a/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java b/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java index ddc536c..d846aa1 100644 --- a/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java +++ b/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java @@ -7,6 +7,7 @@ import com.eactive.eai.adapter.Keys; import com.eactive.eai.adapter.http.HttpMemoryLogger; import com.eactive.eai.adapter.http.HttpMethodType; import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceSupport; +import com.eactive.eai.authserver.service.OAuth2Manager; import com.eactive.eai.common.exception.ExceptionUtil; import com.eactive.eai.common.message.MessageType; import com.eactive.eai.common.util.CommonLib; @@ -18,6 +19,10 @@ import com.eactive.eai.message.StandardMessageUtil; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.kjbank.encrypt.exchange.crypto.AES256Cipher; +import com.kjbank.encrypt.exchange.crypto.AESCipher; + +import edu.emory.mathcs.backport.java.util.Arrays; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.StopWatch; @@ -33,9 +38,32 @@ import org.springframework.util.AntPathMatcher; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; import java.util.*; +//for encrypt/decrypt jwhong +import com.kjbank.encrypt.exchange.crypto.AES256Cipher; +import com.kjbank.encrypt.exchange.crypto.AESCipher; +import java.nio.charset.StandardCharsets; + +import com.eactive.eai.common.util.Logger; +import edu.emory.mathcs.backport.java.util.Arrays; +import java.io.ByteArrayOutputStream; +import java.io.ObjectOutputStream; +import java.io.IOException; +import java.io.Serializable; +import java.io.ByteArrayInputStream; +import java.io.ObjectInputStream; +import com.eactive.eai.authserver.vo.ClientVO; +import org.springframework.security.oauth2.provider.ClientDetails; + @Service public class ApiAdapterService extends HttpAdapterServiceSupport { static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER); @@ -49,7 +77,7 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { private static final String JSON_FIELD_NAME = "json-body"; private static final String FILE_GROUP_NAME = "image-file"; private static final String UPLOAD_ROOT_PATH = "UPLOAD_ROOT_PATH"; - + public String callApi(HttpServletRequest request, HttpServletResponse response, Properties httpProp, AdapterGroupVO adapterGroupVO, AdapterVO adapterVO, Properties transactionProp) throws Exception { int traceLevel = 0; @@ -70,7 +98,7 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { String paramValue = null; String adptMsgType = null; - + transactionProp.put(INBOUND_METHOD, request.getMethod()); transactionProp.put(INBOUND_URI, request.getRequestURI()); transactionProp.put(INBOUND_HEADER, getHeaders(request)); @@ -80,7 +108,7 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { String extUrl = StringUtils.removeStart(request.getRequestURI(), request.getContextPath()); transactionProp.put(INBOUND_EXTURI, extUrl); } else { - transactionProp.put(INBOUND_EXTURI, getExtUri(request)); + transactionProp.put(INBOUND_EXTURI, getExtUri(request)); } transactionProp.put(INBOUND_CLIENT_IP, getClientIp(request)); // Client IP 추가 transactionProp.put(Processor.REQUEST_ACTION, adapterVO.getAdapterGroupVO().getRefClass()); @@ -92,6 +120,13 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { transactionProp.put(ENC_PATHS, httpProp.getProperty(ENC_PATHS, "")); + transactionProp.put(ENCRYPT_ALGORITHM, httpProp.getProperty(ENCRYPT_ALGORITHM, "")); //jwhong + transactionProp.put(HEADER_NAME_CLIENT_ID, getHeaders(request).get(HEADER_NAME_CLIENT_ID)); // jwhong + transactionProp.put(ENCRYPT_BASE_TYPE, httpProp.getProperty(ENCRYPT_BASE_TYPE, "")); //jwhong + //transactionProp.put(INBOUND_TOKEN, getHeaders(request).get(INBOUND_TOKEN)); // jwhong + transactionProp.put(INBOUND_TOKEN, getHeaders(request).get(INBOUND_TOKEN) != null ? getHeaders(request).get(INBOUND_TOKEN) : ""); //jwhong , null 이면 default로 "" put + + try { traceLevel = Integer.parseInt(traceLevelTemp); } catch (Exception e) { @@ -197,6 +232,9 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { if (paramValue == null) { // parameter가 없는 경우때문에 처리 paramValue = ""; + } + else { // jwhong decrypt + paramValue = doPreDecryption(paramValue, transactionProp); } if ("Y".equals(urlDecodeYn) && isParameterType) { @@ -279,6 +317,129 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { return result; } + + + // jwhong encrypt + + private String doPreDecryption(String eaiBody, Properties transactionProp) { + String decryptAlgorithm = transactionProp.getProperty(ENCRYPT_ALGORITHM, ""); + String xElinkClientId = transactionProp.getProperty(HEADER_NAME_CLIENT_ID, ""); // 이 값이 OAuth의 client id 값이다 . http header 에 포함되어 온다. jwhong + String encryptBaseKeyType = transactionProp.getProperty(ENCRYPT_BASE_TYPE); + String inboundToken = transactionProp.getProperty(INBOUND_TOKEN, ""); + + if ( decryptAlgorithm == "" ) { // 복호화 대상이 아님 + return eaiBody; + } + + // 암호화 key를 token 내용으로 할지 client secret 내용으로 할지 결정함. adapter property에 정의함 + // ENCRYPT_ALGORITHM 을 설정했는데 ENCRYPT_BASE_TYPE을 설정안하면 Decrypt 수행시 Exception 발생함 + String clientSecret = ""; + if ("TOKEN".equalsIgnoreCase(encryptBaseKeyType)) { + clientSecret = inboundToken; + } else if ( "SECRETKEY".equalsIgnoreCase(encryptBaseKeyType)) { + OAuth2Manager manager = OAuth2Manager.getInstance(); + ClientDetails clientDetail = manager.getClientDeatilsStore().get(xElinkClientId); + + if ( clientDetail != null ) { + clientSecret = clientDetail.getClientSecret(); + } + } + + byte[] decryptedMessage = null; + decryptedMessage = doInboundPreDecrypt(eaiBody, decryptAlgorithm,clientSecret); + + String resultMessage = new String(decryptedMessage, StandardCharsets.UTF_8 ); + return resultMessage; + //return new String(decryptedMessage, StandardCharsets.UTF_8 ); + } + + + private byte[] convertObjectToBytes(Object obj) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(obj); + oos.flush(); + return bos.toByteArray(); + } + + private byte[] convertObjectToBase64Bytes(Object obj) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(obj); + oos.flush(); + oos.close(); + + // 직렬화된 byte[] → Base64 문자열 → 다시 byte[]로 변환 + String base64String = Base64.getEncoder().encodeToString(bos.toByteArray()); + return base64String.getBytes(StandardCharsets.UTF_8); + } + + public static Object convertBytesToObject(byte[] bytes) throws IOException, ClassNotFoundException { + try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bis)) { + return ois.readObject(); + } + } + + + private byte[] doInboundPreDecrypt(String eaiStringBody, String decryptAlgorithm, String clientSecretKey) { + + byte[] decryptedMessage = null; + //String eaiStringBody = new String(eaiBody, StandardCharsets.UTF_8); + + //test source + //System.out.println("eaiBody 바이트 배열 길이: " + eaiBody.length); + System.out.println("Base64 문자열: " + eaiStringBody); + System.out.println("Base64 문자열 길이: " + eaiStringBody.length()); + System.out.println("Base64 문자열 끝: " + eaiStringBody.substring(eaiStringBody.length() - 10)); + + // Base64 디코딩 테스트 + try { + byte[] decoded = Base64.getDecoder().decode(eaiStringBody); + System.out.println("디코딩 성공, 길이: " + decoded.length); + } catch (IllegalArgumentException e) { + System.out.println("Base64 디코딩 실패: " + e.getMessage()); + } + // end test source + + switch (decryptAlgorithm) { + case "AES128": + + String key128 = clientSecretKey.substring(22,38); //togetherEncoder 경우는 substring(44,60) 이네?? + try { + //String decryptedStrMessage = AESCipher.decrypt(eaiStringBody, key128); + String decryptedStrMessage = AESCipher.decryptExistException(eaiStringBody, key128); + decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES128 Decryption error=" + e.getMessage()); + } + break; + case "AES256": + String key = clientSecretKey.substring(10,42); + try { + String decryptedStrMessage = AES256Cipher.decrypt(eaiStringBody, key); + decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES256 Decryption error=" + e.getMessage()); + } + break; + default: + try { + //decryptedMessage = Arrays.copyOf(eaiBody, eaiBody.length); + decryptedMessage = eaiStringBody.getBytes(); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] doOutboundPostFilter Array copy error=" + e.getMessage()); + } + break; + } + + return decryptedMessage; + } + + // jwhong until here private Map assignParameterMap(HttpServletRequest request, String adptGrpName, String adptName, From 6f26e949c583e6c276e45fba1c93fbde44b2caac Mon Sep 17 00:00:00 2001 From: jaewohong Date: Mon, 13 Oct 2025 15:10:07 +0900 Subject: [PATCH 05/21] =?UTF-8?q?=EC=95=94=ED=98=B8=ED=99=94=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/service/ApiAdapterService.java | 22 +++---------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java b/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java index d846aa1..2bb510e 100644 --- a/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java +++ b/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java @@ -7,7 +7,6 @@ import com.eactive.eai.adapter.Keys; import com.eactive.eai.adapter.http.HttpMemoryLogger; import com.eactive.eai.adapter.http.HttpMethodType; import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceSupport; -import com.eactive.eai.authserver.service.OAuth2Manager; import com.eactive.eai.common.exception.ExceptionUtil; import com.eactive.eai.common.message.MessageType; import com.eactive.eai.common.util.CommonLib; @@ -19,16 +18,12 @@ import com.eactive.eai.message.StandardMessageUtil; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; -import com.kjbank.encrypt.exchange.crypto.AES256Cipher; -import com.kjbank.encrypt.exchange.crypto.AESCipher; - -import edu.emory.mathcs.backport.java.util.Arrays; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.StopWatch; import org.apache.mina.common.ByteBuffer; import org.json.simple.JSONObject; -import org.json.simple.JSONValue; +import org.json.simple.JSONValue; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; @@ -38,30 +33,19 @@ import org.springframework.util.AntPathMatcher; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; import java.net.URLDecoder; -import java.nio.charset.StandardCharsets; import java.util.*; //for encrypt/decrypt jwhong +import com.eactive.eai.authserver.service.OAuth2Manager; import com.kjbank.encrypt.exchange.crypto.AES256Cipher; import com.kjbank.encrypt.exchange.crypto.AESCipher; import java.nio.charset.StandardCharsets; - -import com.eactive.eai.common.util.Logger; -import edu.emory.mathcs.backport.java.util.Arrays; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectOutputStream; import java.io.IOException; -import java.io.Serializable; -import java.io.ByteArrayInputStream; import java.io.ObjectInputStream; -import com.eactive.eai.authserver.vo.ClientVO; import org.springframework.security.oauth2.provider.ClientDetails; @Service From bb068cce206731ea6a5a40af1ae04d9afa2d1a4c Mon Sep 17 00:00:00 2001 From: jaewohong Date: Mon, 13 Oct 2025 15:20:52 +0900 Subject: [PATCH 06/21] =?UTF-8?q?KJBank=20=EC=95=94=ED=98=B8=ED=99=94=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EB=B0=8F=20Sync=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- WebContent/META-INF/context.xml | 36 +++++++++++++++++++++++++++++++++ elink-online-common | 2 +- elink-online-core | 2 +- elink-online-core-jpa | 2 +- elink-online-emsclient | 2 +- elink-online-transformer | 2 +- 6 files changed, 41 insertions(+), 5 deletions(-) diff --git a/WebContent/META-INF/context.xml b/WebContent/META-INF/context.xml index 8e8180c..e2156df 100644 --- a/WebContent/META-INF/context.xml +++ b/WebContent/META-INF/context.xml @@ -25,9 +25,45 @@ +<<<<<<< HEAD +======= + + + + + + + + + + + + + + + +>>>>>>> 05596e9 (KJBank 암호화 관련 및 Sync 관련 수정) \ No newline at end of file diff --git a/elink-online-common b/elink-online-common index aacc1a3..8ba0b6e 160000 --- a/elink-online-common +++ b/elink-online-common @@ -1 +1 @@ -Subproject commit aacc1a389e145453cf92c18e9d7ffef568cf89e7 +Subproject commit 8ba0b6ee9c9fe1f751be5ee5e727b73faccb80ee diff --git a/elink-online-core b/elink-online-core index 0f148e9..668aca0 160000 --- a/elink-online-core +++ b/elink-online-core @@ -1 +1 @@ -Subproject commit 0f148e997ec808e01a013baa8ca7b0053a69fe22 +Subproject commit 668aca0ff96e021096ba3add447e36a3c05b4535 diff --git a/elink-online-core-jpa b/elink-online-core-jpa index 2cd9c29..33cf6fb 160000 --- a/elink-online-core-jpa +++ b/elink-online-core-jpa @@ -1 +1 @@ -Subproject commit 2cd9c29d4df228c1ffd7ed6471c8245510b19213 +Subproject commit 33cf6fbd3d5914095d2ef57c72888560bbdb3ac3 diff --git a/elink-online-emsclient b/elink-online-emsclient index f68423b..b5f62fd 160000 --- a/elink-online-emsclient +++ b/elink-online-emsclient @@ -1 +1 @@ -Subproject commit f68423b40ecb5076990739f09f87ec62f7fd17ae +Subproject commit b5f62fda76bdbb1f50f2427abf3979edad87610f diff --git a/elink-online-transformer b/elink-online-transformer index c3e2de4..3e16b13 160000 --- a/elink-online-transformer +++ b/elink-online-transformer @@ -1 +1 @@ -Subproject commit c3e2de482be0fa692a5133cf77e0e3dc86357b6e +Subproject commit 3e16b13d7265518ad140433273101a9d4a4f694d From 1a5cf2c78ff663471f748e4e5231cfe7b061507d Mon Sep 17 00:00:00 2001 From: jaewohong Date: Mon, 13 Oct 2025 14:47:47 +0900 Subject: [PATCH 07/21] =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/service/ApiAdapterService.java | 139 +----------------- 1 file changed, 3 insertions(+), 136 deletions(-) diff --git a/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java b/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java index 2bb510e..6a72af8 100644 --- a/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java +++ b/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java @@ -61,7 +61,7 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { private static final String JSON_FIELD_NAME = "json-body"; private static final String FILE_GROUP_NAME = "image-file"; private static final String UPLOAD_ROOT_PATH = "UPLOAD_ROOT_PATH"; - + public String callApi(HttpServletRequest request, HttpServletResponse response, Properties httpProp, AdapterGroupVO adapterGroupVO, AdapterVO adapterVO, Properties transactionProp) throws Exception { int traceLevel = 0; @@ -82,7 +82,7 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { String paramValue = null; String adptMsgType = null; - + transactionProp.put(INBOUND_METHOD, request.getMethod()); transactionProp.put(INBOUND_URI, request.getRequestURI()); transactionProp.put(INBOUND_HEADER, getHeaders(request)); @@ -92,7 +92,7 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { String extUrl = StringUtils.removeStart(request.getRequestURI(), request.getContextPath()); transactionProp.put(INBOUND_EXTURI, extUrl); } else { - transactionProp.put(INBOUND_EXTURI, getExtUri(request)); + transactionProp.put(INBOUND_EXTURI, getExtUri(request)); } transactionProp.put(INBOUND_CLIENT_IP, getClientIp(request)); // Client IP 추가 transactionProp.put(Processor.REQUEST_ACTION, adapterVO.getAdapterGroupVO().getRefClass()); @@ -104,13 +104,6 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { transactionProp.put(ENC_PATHS, httpProp.getProperty(ENC_PATHS, "")); - transactionProp.put(ENCRYPT_ALGORITHM, httpProp.getProperty(ENCRYPT_ALGORITHM, "")); //jwhong - transactionProp.put(HEADER_NAME_CLIENT_ID, getHeaders(request).get(HEADER_NAME_CLIENT_ID)); // jwhong - transactionProp.put(ENCRYPT_BASE_TYPE, httpProp.getProperty(ENCRYPT_BASE_TYPE, "")); //jwhong - //transactionProp.put(INBOUND_TOKEN, getHeaders(request).get(INBOUND_TOKEN)); // jwhong - transactionProp.put(INBOUND_TOKEN, getHeaders(request).get(INBOUND_TOKEN) != null ? getHeaders(request).get(INBOUND_TOKEN) : ""); //jwhong , null 이면 default로 "" put - - try { traceLevel = Integer.parseInt(traceLevelTemp); } catch (Exception e) { @@ -216,9 +209,6 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { if (paramValue == null) { // parameter가 없는 경우때문에 처리 paramValue = ""; - } - else { // jwhong decrypt - paramValue = doPreDecryption(paramValue, transactionProp); } if ("Y".equals(urlDecodeYn) && isParameterType) { @@ -301,129 +291,6 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { return result; } - - - // jwhong encrypt - - private String doPreDecryption(String eaiBody, Properties transactionProp) { - String decryptAlgorithm = transactionProp.getProperty(ENCRYPT_ALGORITHM, ""); - String xElinkClientId = transactionProp.getProperty(HEADER_NAME_CLIENT_ID, ""); // 이 값이 OAuth의 client id 값이다 . http header 에 포함되어 온다. jwhong - String encryptBaseKeyType = transactionProp.getProperty(ENCRYPT_BASE_TYPE); - String inboundToken = transactionProp.getProperty(INBOUND_TOKEN, ""); - - if ( decryptAlgorithm == "" ) { // 복호화 대상이 아님 - return eaiBody; - } - - // 암호화 key를 token 내용으로 할지 client secret 내용으로 할지 결정함. adapter property에 정의함 - // ENCRYPT_ALGORITHM 을 설정했는데 ENCRYPT_BASE_TYPE을 설정안하면 Decrypt 수행시 Exception 발생함 - String clientSecret = ""; - if ("TOKEN".equalsIgnoreCase(encryptBaseKeyType)) { - clientSecret = inboundToken; - } else if ( "SECRETKEY".equalsIgnoreCase(encryptBaseKeyType)) { - OAuth2Manager manager = OAuth2Manager.getInstance(); - ClientDetails clientDetail = manager.getClientDeatilsStore().get(xElinkClientId); - - if ( clientDetail != null ) { - clientSecret = clientDetail.getClientSecret(); - } - } - - byte[] decryptedMessage = null; - decryptedMessage = doInboundPreDecrypt(eaiBody, decryptAlgorithm,clientSecret); - - String resultMessage = new String(decryptedMessage, StandardCharsets.UTF_8 ); - return resultMessage; - //return new String(decryptedMessage, StandardCharsets.UTF_8 ); - } - - - private byte[] convertObjectToBytes(Object obj) throws IOException { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(bos); - oos.writeObject(obj); - oos.flush(); - return bos.toByteArray(); - } - - private byte[] convertObjectToBase64Bytes(Object obj) throws IOException { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(bos); - oos.writeObject(obj); - oos.flush(); - oos.close(); - - // 직렬화된 byte[] → Base64 문자열 → 다시 byte[]로 변환 - String base64String = Base64.getEncoder().encodeToString(bos.toByteArray()); - return base64String.getBytes(StandardCharsets.UTF_8); - } - - public static Object convertBytesToObject(byte[] bytes) throws IOException, ClassNotFoundException { - try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes); - ObjectInputStream ois = new ObjectInputStream(bis)) { - return ois.readObject(); - } - } - - - private byte[] doInboundPreDecrypt(String eaiStringBody, String decryptAlgorithm, String clientSecretKey) { - - byte[] decryptedMessage = null; - //String eaiStringBody = new String(eaiBody, StandardCharsets.UTF_8); - - //test source - //System.out.println("eaiBody 바이트 배열 길이: " + eaiBody.length); - System.out.println("Base64 문자열: " + eaiStringBody); - System.out.println("Base64 문자열 길이: " + eaiStringBody.length()); - System.out.println("Base64 문자열 끝: " + eaiStringBody.substring(eaiStringBody.length() - 10)); - - // Base64 디코딩 테스트 - try { - byte[] decoded = Base64.getDecoder().decode(eaiStringBody); - System.out.println("디코딩 성공, 길이: " + decoded.length); - } catch (IllegalArgumentException e) { - System.out.println("Base64 디코딩 실패: " + e.getMessage()); - } - // end test source - - switch (decryptAlgorithm) { - case "AES128": - - String key128 = clientSecretKey.substring(22,38); //togetherEncoder 경우는 substring(44,60) 이네?? - try { - //String decryptedStrMessage = AESCipher.decrypt(eaiStringBody, key128); - String decryptedStrMessage = AESCipher.decryptExistException(eaiStringBody, key128); - decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); - } catch (Exception e) { - e.printStackTrace(); - logger.error("HttpClientAdapterServiceRest] AES128 Decryption error=" + e.getMessage()); - } - break; - case "AES256": - String key = clientSecretKey.substring(10,42); - try { - String decryptedStrMessage = AES256Cipher.decrypt(eaiStringBody, key); - decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); - } catch (Exception e) { - e.printStackTrace(); - logger.error("HttpClientAdapterServiceRest] AES256 Decryption error=" + e.getMessage()); - } - break; - default: - try { - //decryptedMessage = Arrays.copyOf(eaiBody, eaiBody.length); - decryptedMessage = eaiStringBody.getBytes(); - } catch (Exception e) { - e.printStackTrace(); - logger.error("HttpClientAdapterServiceRest] doOutboundPostFilter Array copy error=" + e.getMessage()); - } - break; - } - - return decryptedMessage; - } - - // jwhong until here private Map assignParameterMap(HttpServletRequest request, String adptGrpName, String adptName, From 70a5f4d9d4e676aa78514677031af98fadc784d6 Mon Sep 17 00:00:00 2001 From: jaewohong Date: Mon, 13 Oct 2025 15:02:20 +0900 Subject: [PATCH 08/21] =?UTF-8?q?=EC=95=94=ED=98=B8=ED=99=94=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eai/adapter/service/ApiAdapterService.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java b/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java index 6a72af8..9ff80e3 100644 --- a/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java +++ b/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java @@ -36,18 +36,6 @@ import javax.servlet.http.HttpServletResponse; import java.net.URLDecoder; import java.util.*; -//for encrypt/decrypt jwhong -import com.eactive.eai.authserver.service.OAuth2Manager; -import com.kjbank.encrypt.exchange.crypto.AES256Cipher; -import com.kjbank.encrypt.exchange.crypto.AESCipher; -import java.nio.charset.StandardCharsets; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.ObjectOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import org.springframework.security.oauth2.provider.ClientDetails; - @Service public class ApiAdapterService extends HttpAdapterServiceSupport { static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER); From 430cf9a5af38199159a5e95b3eb2683f39ca87c0 Mon Sep 17 00:00:00 2001 From: jaewohong Date: Mon, 13 Oct 2025 15:25:18 +0900 Subject: [PATCH 09/21] aaaa --- .../eai/adapter/service/ApiAdapterService.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java b/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java index 9ff80e3..f527741 100644 --- a/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java +++ b/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java @@ -23,7 +23,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.StopWatch; import org.apache.mina.common.ByteBuffer; import org.json.simple.JSONObject; -import org.json.simple.JSONValue; +import org.json.simple.JSONValue; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; @@ -36,6 +36,19 @@ import javax.servlet.http.HttpServletResponse; import java.net.URLDecoder; import java.util.*; +//for encrypt/decrypt jwhong +import com.eactive.eai.authserver.service.OAuth2Manager; +import com.kjbank.encrypt.exchange.crypto.AES256Cipher; +import com.kjbank.encrypt.exchange.crypto.AESCipher; +import java.nio.charset.StandardCharsets; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import org.springframework.security.oauth2.provider.ClientDetails; + + @Service public class ApiAdapterService extends HttpAdapterServiceSupport { static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER); From bf0f77838fec2803ce58be35cfd8563dc5d0d8be Mon Sep 17 00:00:00 2001 From: jaewohong Date: Mon, 13 Oct 2025 16:24:57 +0900 Subject: [PATCH 10/21] =?UTF-8?q?KJBank=20=EC=95=94=ED=98=B8=ED=99=94=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/service/ApiAdapterService.java | 140 +++++++++++++++++- 1 file changed, 136 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java b/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java index f527741..77b80b4 100644 --- a/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java +++ b/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java @@ -48,7 +48,6 @@ import java.io.IOException; import java.io.ObjectInputStream; import org.springframework.security.oauth2.provider.ClientDetails; - @Service public class ApiAdapterService extends HttpAdapterServiceSupport { static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER); @@ -62,7 +61,7 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { private static final String JSON_FIELD_NAME = "json-body"; private static final String FILE_GROUP_NAME = "image-file"; private static final String UPLOAD_ROOT_PATH = "UPLOAD_ROOT_PATH"; - + public String callApi(HttpServletRequest request, HttpServletResponse response, Properties httpProp, AdapterGroupVO adapterGroupVO, AdapterVO adapterVO, Properties transactionProp) throws Exception { int traceLevel = 0; @@ -83,7 +82,7 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { String paramValue = null; String adptMsgType = null; - + transactionProp.put(INBOUND_METHOD, request.getMethod()); transactionProp.put(INBOUND_URI, request.getRequestURI()); transactionProp.put(INBOUND_HEADER, getHeaders(request)); @@ -93,7 +92,7 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { String extUrl = StringUtils.removeStart(request.getRequestURI(), request.getContextPath()); transactionProp.put(INBOUND_EXTURI, extUrl); } else { - transactionProp.put(INBOUND_EXTURI, getExtUri(request)); + transactionProp.put(INBOUND_EXTURI, getExtUri(request)); } transactionProp.put(INBOUND_CLIENT_IP, getClientIp(request)); // Client IP 추가 transactionProp.put(Processor.REQUEST_ACTION, adapterVO.getAdapterGroupVO().getRefClass()); @@ -105,6 +104,13 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { transactionProp.put(ENC_PATHS, httpProp.getProperty(ENC_PATHS, "")); + transactionProp.put(ENCRYPT_ALGORITHM, httpProp.getProperty(ENCRYPT_ALGORITHM, "")); //jwhong + transactionProp.put(HEADER_NAME_CLIENT_ID, getHeaders(request).get(HEADER_NAME_CLIENT_ID)); // jwhong + transactionProp.put(ENCRYPT_BASE_TYPE, httpProp.getProperty(ENCRYPT_BASE_TYPE, "")); //jwhong + //transactionProp.put(INBOUND_TOKEN, getHeaders(request).get(INBOUND_TOKEN)); // jwhong + transactionProp.put(INBOUND_TOKEN, getHeaders(request).get(INBOUND_TOKEN) != null ? getHeaders(request).get(INBOUND_TOKEN) : ""); //jwhong , null 이면 default로 "" put + + try { traceLevel = Integer.parseInt(traceLevelTemp); } catch (Exception e) { @@ -210,6 +216,9 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { if (paramValue == null) { // parameter가 없는 경우때문에 처리 paramValue = ""; + } + else { // jwhong decrypt + paramValue = doPreDecryption(paramValue, transactionProp); } if ("Y".equals(urlDecodeYn) && isParameterType) { @@ -292,6 +301,129 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { return result; } + + + // jwhong encrypt + + private String doPreDecryption(String eaiBody, Properties transactionProp) { + String decryptAlgorithm = transactionProp.getProperty(ENCRYPT_ALGORITHM, ""); + String xElinkClientId = transactionProp.getProperty(HEADER_NAME_CLIENT_ID, ""); // 이 값이 OAuth의 client id 값이다 . http header 에 포함되어 온다. jwhong + String encryptBaseKeyType = transactionProp.getProperty(ENCRYPT_BASE_TYPE); + String inboundToken = transactionProp.getProperty(INBOUND_TOKEN, ""); + + if ( decryptAlgorithm == "" ) { // 복호화 대상이 아님 + return eaiBody; + } + + // 암호화 key를 token 내용으로 할지 client secret 내용으로 할지 결정함. adapter property에 정의함 + // ENCRYPT_ALGORITHM 을 설정했는데 ENCRYPT_BASE_TYPE을 설정안하면 Decrypt 수행시 Exception 발생함 + String clientSecret = ""; + if ("TOKEN".equalsIgnoreCase(encryptBaseKeyType)) { + clientSecret = inboundToken; + } else if ( "SECRETKEY".equalsIgnoreCase(encryptBaseKeyType)) { + OAuth2Manager manager = OAuth2Manager.getInstance(); + ClientDetails clientDetail = manager.getClientDeatilsStore().get(xElinkClientId); + + if ( clientDetail != null ) { + clientSecret = clientDetail.getClientSecret(); + } + } + + byte[] decryptedMessage = null; + decryptedMessage = doInboundPreDecrypt(eaiBody, decryptAlgorithm,clientSecret); + + String resultMessage = new String(decryptedMessage, StandardCharsets.UTF_8 ); + return resultMessage; + //return new String(decryptedMessage, StandardCharsets.UTF_8 ); + } + + + private byte[] convertObjectToBytes(Object obj) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(obj); + oos.flush(); + return bos.toByteArray(); + } + + private byte[] convertObjectToBase64Bytes(Object obj) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(obj); + oos.flush(); + oos.close(); + + // 직렬화된 byte[] → Base64 문자열 → 다시 byte[]로 변환 + String base64String = Base64.getEncoder().encodeToString(bos.toByteArray()); + return base64String.getBytes(StandardCharsets.UTF_8); + } + + public static Object convertBytesToObject(byte[] bytes) throws IOException, ClassNotFoundException { + try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bis)) { + return ois.readObject(); + } + } + + + private byte[] doInboundPreDecrypt(String eaiStringBody, String decryptAlgorithm, String clientSecretKey) { + + byte[] decryptedMessage = null; + //String eaiStringBody = new String(eaiBody, StandardCharsets.UTF_8); + + //test source + //System.out.println("eaiBody 바이트 배열 길이: " + eaiBody.length); + System.out.println("Base64 문자열: " + eaiStringBody); + System.out.println("Base64 문자열 길이: " + eaiStringBody.length()); + System.out.println("Base64 문자열 끝: " + eaiStringBody.substring(eaiStringBody.length() - 10)); + + // Base64 디코딩 테스트 + try { + byte[] decoded = Base64.getDecoder().decode(eaiStringBody); + System.out.println("디코딩 성공, 길이: " + decoded.length); + } catch (IllegalArgumentException e) { + System.out.println("Base64 디코딩 실패: " + e.getMessage()); + } + // end test source + + switch (decryptAlgorithm) { + case "AES128": + + String key128 = clientSecretKey.substring(22,38); //togetherEncoder 경우는 substring(44,60) 이네?? + try { + //String decryptedStrMessage = AESCipher.decrypt(eaiStringBody, key128); + String decryptedStrMessage = AESCipher.decryptExistException(eaiStringBody, key128); + decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES128 Decryption error=" + e.getMessage()); + } + break; + case "AES256": + String key = clientSecretKey.substring(10,42); + try { + String decryptedStrMessage = AES256Cipher.decrypt(eaiStringBody, key); + decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES256 Decryption error=" + e.getMessage()); + } + break; + default: + try { + //decryptedMessage = Arrays.copyOf(eaiBody, eaiBody.length); + decryptedMessage = eaiStringBody.getBytes(); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] doOutboundPostFilter Array copy error=" + e.getMessage()); + } + break; + } + + return decryptedMessage; + } + + // jwhong until here private Map assignParameterMap(HttpServletRequest request, String adptGrpName, String adptName, From 4c4a22a2a58e847541162a671d745a7731e7bad4 Mon Sep 17 00:00:00 2001 From: jaewohong Date: Mon, 13 Oct 2025 16:31:54 +0900 Subject: [PATCH 11/21] =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- WebContent/META-INF/context.xml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/WebContent/META-INF/context.xml b/WebContent/META-INF/context.xml index e2156df..385912e 100644 --- a/WebContent/META-INF/context.xml +++ b/WebContent/META-INF/context.xml @@ -25,12 +25,6 @@ -<<<<<<< HEAD - -======= - + authserver @@ -71,6 +70,7 @@ + + authserver diff --git a/WebContent/WEB-INF/weblogic-web.xml b/WebContent/WEB-INF/weblogic-web.xml index 3e0192a..2e359f1 100644 --- a/WebContent/WEB-INF/weblogic-web.xml +++ b/WebContent/WEB-INF/weblogic-web.xml @@ -35,6 +35,16 @@ /WEB-INF/applicationContext.xml + + + default + weblogic.servlet.FileServlet + + + default + /static/* + + authserver From 48ada81aeb563929ba2d308bf140e5467b8a157a Mon Sep 17 00:00:00 2001 From: Yunsam Date: Wed, 5 Nov 2025 20:34:43 +0900 Subject: [PATCH 19/21] =?UTF-8?q?Weblogic=20Default=20Servlet=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- WebContent/WEB-INF/web.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/WebContent/WEB-INF/web.xml b/WebContent/WEB-INF/web.xml index 78e0ce6..cc3d507 100644 --- a/WebContent/WEB-INF/web.xml +++ b/WebContent/WEB-INF/web.xml @@ -35,7 +35,6 @@ /WEB-INF/applicationContext.xml - + authserver From 360c1dfbafba8b2a6d4c92f62db41db24aa5b2b4 Mon Sep 17 00:00:00 2001 From: 25W0075 <25W0075@P9801Z.kjbank.dom> Date: Mon, 17 Nov 2025 15:33:39 +0900 Subject: [PATCH 20/21] =?UTF-8?q?/mapi=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ApiAdapterController.java | 441 ++++++++++-------- 1 file changed, 252 insertions(+), 189 deletions(-) diff --git a/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java b/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java index 0b60677..1427b68 100644 --- a/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java +++ b/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java @@ -1,190 +1,253 @@ -package com.eactive.eai.adapter.controller; - -import java.util.Date; -import java.util.Properties; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import com.eactive.eai.adapter.AdapterGroupVO; -import com.eactive.eai.adapter.AdapterManager; -import com.eactive.eai.adapter.AdapterPropManager; -import com.eactive.eai.adapter.AdapterVO; -import com.eactive.eai.adapter.http.HttpStatusException; -import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceKey; -import com.eactive.eai.adapter.http.dynamic.HttpDynamicInAdapterManager; -import com.eactive.eai.adapter.http.dynamic.HttpDynamicInAdapterUri; -import com.eactive.eai.adapter.http.dynamic.filter.JwtAuthException; -import com.eactive.eai.adapter.service.ApiAdapterService; -import com.eactive.eai.common.TransactionContextKeys; -import com.eactive.eai.common.exception.ExceptionUtil; -import com.eactive.eai.common.server.EAIServerManager; -import com.eactive.eai.common.util.DatetimeUtil; -import com.eactive.eai.common.util.InboundErrorLogger; -import com.eactive.eai.common.util.Logger; -import com.eactive.eai.common.util.MessageUtil; -import com.eactive.eai.common.util.UUIDGenerator; -import com.eactive.eai.inbound.error.InboundErrorInfoVO; - -@RestController -public class ApiAdapterController implements HttpAdapterServiceKey { - static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER); - - @Autowired - ApiAdapterService service; - - /** - * KBANK 요구사항으로 /api/v1/oauth/token 과 같은 형태로 토큰 발급거래를 수행해야해서 예외처리함 - * @See com.eactive.eai.authserver.config.AuthorizationServerConfig.configure(AuthorizationServerEndpointsConfigurer endpoints) - */ - @RequestMapping(value = {"/api/*", "/api/*/{path:^(?!.*oauth).*$}/**"}) -// @RequestMapping(value = {"/api/**"}) - public ResponseEntity callApi(HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws Exception { - // /ONLWeb/api/v1/public/getUserInfo.svc - String apiUri = servletRequest.getRequestURI(); - // /api/v1/public/getUserInfo.svc - apiUri = StringUtils.removeStart(apiUri, servletRequest.getContextPath()); - apiUri = StringUtils.removeEnd(apiUri, "/"); - HttpDynamicInAdapterUri adptUri = findAdptUri(apiUri, HttpDynamicInAdapterManager.getInstance()); - - if (logger.isDebug()) { - logger.debug("ApiAdapterController] service request uri : " + servletRequest.getRequestURI()); - } - - if (adptUri == null) { - logError(servletRequest); -// throw new Exception("can not find Adapter Uri"); - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("can not find Adapter Uri"); - } - - - String adapterGroupName = adptUri.getAdptGrpName(); - String adapterName = adptUri.getAdptName(); - AdapterGroupVO adapterGroupVO = AdapterManager.getInstance().getAdapterGroupVO(adapterGroupName); - AdapterVO adapterVO = AdapterManager.getInstance().getAdapterVO(adapterGroupName, adapterName); - if (adapterVO == null) { -// throw new Exception("Adapter not found error"); - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Adapter not found error"); - } - - Properties httpProp = AdapterPropManager.getInstance().getProperties(adapterVO.getPropGroupName()); - - String adptMsgType = adapterVO.getAdapterGroupVO().getMessageType(); - String encode = StringUtils.defaultIfBlank(adapterGroupVO.getMessageEncode(), "UTF-8"); - MediaType mediaType = MediaType.valueOf("application/json;charset=" + encode); - String errorResponseFormat = httpProp.getProperty(ERROR_RESPONSE_FORMAT); - - String responseType = httpProp.getProperty(RESPONSE_TYPE, "SYNC"); - ResponseEntity responseEntity = null; - Properties transactionProp = new Properties(); - try { - String responseData = service.callApi(servletRequest, servletResponse, httpProp, adapterGroupVO, adapterVO, transactionProp); - if (RESPONSE_TYPE_ASYNC.equals(responseType)) { - responseEntity = ResponseEntity.ok("dummy"); - } else { -// responseEntity = ResponseEntity.ok().contentType(mediaType).body(responseData); -// 버즈빌 포인트 적립 처리하기 위하여 정상응답이더라도 응답코드(apiRsltCd) 값이 200이 아닌 경우 처리를 위하여 수정 -// Filter에서 설정한 response status값을 responseEntity 생성시 적용 modify by lwk 2025.03.24 - int httpStatus = servletResponse.getStatus(); - if (httpStatus != 200) { - responseEntity = ResponseEntity.status(httpStatus).contentType(mediaType).body(responseData); - } else { - responseEntity = ResponseEntity.ok().contentType(mediaType).body(responseData); - } - } - } catch (HttpStatusException e) { - logger.warn("ApiAdapterController] " + adapterGroupName + "-" + adapterName + ">>" + e.getMessage()); - String errorMsg = MessageUtil.makeErrorMessageByMessageType(adptMsgType, encode, e.getCode(), - e.getMessage(), errorResponseFormat); - responseEntity = ResponseEntity.status(e.getStatus()).contentType(mediaType).body(errorMsg); - } catch (JwtAuthException e) { - logger.error(adapterGroupName + "-" + adapterName + ">>" + e.getMessage(), e); - String errorMsg = MessageUtil.makeErrorMessageByMessageType(adptMsgType, encode, e.getCode(), - e.getMessage(), errorResponseFormat); - responseEntity = ResponseEntity.status(HttpStatus.UNAUTHORIZED).contentType(mediaType).body(errorMsg); - } catch (Exception e) { - logger.error(adapterGroupName + "-" + adapterName + ">>" + e.getMessage(), e); - responseEntity = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).contentType(mediaType).body(e); - } finally { - /** - * 로깅 인터셉터에 데이터를 전달하기 위한 처리 - * 이미 거래처리가 끝나서 영향도가 없을만한 servletRequest에 Attribute로 전달 - * 추후 더 좋은방법이 생길경우 개선 요망 - */ - servletRequest.setAttribute(TransactionContextKeys.TRANSACTION_PROP, transactionProp); - } - return responseEntity; - } - - - - /** - * url에서 뒤쪽 /이후를 제거하면서 찾는다.
- * /api/v1/public/getUserInfo.svc - * - * @param apiUri - * @return - */ - private HttpDynamicInAdapterUri findAdptUri(String apiUri, HttpDynamicInAdapterManager manager) { - if (StringUtils.isBlank(apiUri)) { - return null; - } - - for (int i = 0; i < 10; i++) { - HttpDynamicInAdapterUri adptUri = manager.getAdptUri(apiUri); - if (adptUri != null) { - return adptUri; - } - - // /api/v1/public - apiUri = StringUtils.substringBeforeLast(apiUri, "/"); - if (apiUri.length() < 4) { // /api - return null; - } - } - - return null; - } - - private void logError(HttpServletRequest request) { - InboundErrorInfoVO errorInfoVO = new InboundErrorInfoVO(); - - EAIServerManager eaiServerManager = EAIServerManager.getInstance(); - String serverName = eaiServerManager.getLocalServerName(); - String uuid = null; - StringBuffer sb = new StringBuffer(); - - String instanceid1 = serverName.substring(0, 2); - String instanceid2 = serverName.substring(serverName.length() - 2, serverName.length()); - String instid = instanceid1 + instanceid2; - uuid = instid + UUIDGenerator.getUUID(); - - String[] msgArgs = new String[1]; - msgArgs[0] = request.getRequestURI(); - - String errorCode = "RECEAIIRP010"; - String errorMsg = ExceptionUtil.make(new Exception("cat not find uri"), errorCode, msgArgs); - - errorInfoVO.setEaiSvcSno(uuid); // EAI서비스일련번호 - errorInfoVO.setAdptBwkGrpNm("HTTP_IN_NO_URI"); // 어댑터업무그룹명 - errorInfoVO.setErrCd(errorCode); // 에러코드 - errorInfoVO.setErrTxt(errorMsg); // 에러내용 - errorInfoVO.setErrTm(DatetimeUtil.getCurrentTime(new Date().getTime())); // 에러발생시각 - errorInfoVO.setErrDstcd(" "); - sb.append("Remote Addr : ").append(request.getRemoteAddr()).append("\n").append("Request URI : ") - .append(request.getRequestURI()); - errorInfoVO.setBwkDataTxt(sb.toString()); // 업무데이터내용 - errorInfoVO.setEaiSvrInstNm(serverName); // EAI서버인스턴스명 - - InboundErrorLogger.error(errorInfoVO); - } - +package com.eactive.eai.adapter.controller; + +import java.util.Date; +import java.util.Properties; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.eactive.eai.adapter.AdapterGroupVO; +import com.eactive.eai.adapter.AdapterManager; +import com.eactive.eai.adapter.AdapterPropManager; +import com.eactive.eai.adapter.AdapterVO; +import com.eactive.eai.adapter.http.HttpStatusException; +import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceKey; +import com.eactive.eai.adapter.http.dynamic.HttpDynamicInAdapterManager; +import com.eactive.eai.adapter.http.dynamic.HttpDynamicInAdapterUri; +import com.eactive.eai.adapter.http.dynamic.filter.JwtAuthException; +import com.eactive.eai.adapter.service.ApiAdapterService; +import com.eactive.eai.common.TransactionContextKeys; +import com.eactive.eai.common.exception.ExceptionUtil; +import com.eactive.eai.common.server.EAIServerManager; +import com.eactive.eai.common.util.DatetimeUtil; +import com.eactive.eai.common.util.InboundErrorLogger; +import com.eactive.eai.common.util.Logger; +import com.eactive.eai.common.util.MessageUtil; +import com.eactive.eai.common.util.UUIDGenerator; +import com.eactive.eai.inbound.error.InboundErrorInfoVO; +import com.kjbank.encrypt.exchange.crypto.AES256Cipher; +import com.kjbank.encrypt.exchange.crypto.AES256GCMCipher; +import com.kjbank.encrypt.exchange.crypto.AESCipher; + +// jwhong +import org.json.simple.JSONObject; +import java.util.HashMap; +import java.util.Map; +import java.sql.Timestamp; + +@RestController +public class ApiAdapterController implements HttpAdapterServiceKey { + static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER); + + @Autowired + ApiAdapterService service; + + /** + * KBANK 요구사항으로 /api/v1/oauth/token 과 같은 형태로 토큰 발급거래를 수행해야해서 예외처리함 + * @See com.eactive.eai.authserver.config.AuthorizationServerConfig.configure(AuthorizationServerEndpointsConfigurer endpoints) + */ + @RequestMapping(value = {"/api/*", "/mapi/*", "/api/*/{path:^(?!.*oauth).*$}/**", "/mapi/*/{path:^(?!.*oauth).*$}/**"}) +// @RequestMapping(value = {"/api/**"}) + public ResponseEntity callApi(HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws Exception { + // /ONLWeb/api/v1/public/getUserInfo.svc + String apiUri = servletRequest.getRequestURI(); + // /api/v1/public/getUserInfo.svc + apiUri = StringUtils.removeStart(apiUri, servletRequest.getContextPath()); + apiUri = StringUtils.removeEnd(apiUri, "/"); + HttpDynamicInAdapterUri adptUri = findAdptUri(apiUri, HttpDynamicInAdapterManager.getInstance()); + + //Received time , jwhong + long receivedTimeMillis = System.currentTimeMillis(); + String receivedTimeStr = String.valueOf(receivedTimeMillis); + + System.out.println("현재 시간 밀리초(long): " + receivedTimeMillis); + System.out.println("현재 시간 밀리초(String): " + receivedTimeStr); + //Timestamp timestamp = new Timestamp(System.currentTimeMillis()); + //System.out.println("현재 Timestamp: " + timestamp); + + if (logger.isDebug()) { + logger.debug("ApiAdapterController] service request uri : " + servletRequest.getRequestURI()); + } + + if (adptUri == null) { + logError(servletRequest); +// throw new Exception("can not find Adapter Uri"); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("can not find Adapter Uri"); + } + + + String adapterGroupName = adptUri.getAdptGrpName(); + String adapterName = adptUri.getAdptName(); + AdapterGroupVO adapterGroupVO = AdapterManager.getInstance().getAdapterGroupVO(adapterGroupName); + AdapterVO adapterVO = AdapterManager.getInstance().getAdapterVO(adapterGroupName, adapterName); + if (adapterVO == null) { +// throw new Exception("Adapter not found error"); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Adapter not found error"); + } + + Properties httpProp = AdapterPropManager.getInstance().getProperties(adapterVO.getPropGroupName()); + + String adptMsgType = adapterVO.getAdapterGroupVO().getMessageType(); + String encode = StringUtils.defaultIfBlank(adapterGroupVO.getMessageEncode(), "UTF-8"); + MediaType mediaType = MediaType.valueOf("application/json;charset=" + encode); + String errorResponseFormat = httpProp.getProperty(ERROR_RESPONSE_FORMAT); + + String responseType = httpProp.getProperty(RESPONSE_TYPE, "SYNC"); + ResponseEntity responseEntity = null; + Properties transactionProp = new Properties(); + //transactionProp.put(INBOUND_REQUESTED_TIME, receivedTimeMillis); // jwhong, put api received time + transactionProp.put(INBOUND_REQUESTED_TIME, receivedTimeStr); + + try { + String responseData = service.callApi(servletRequest, servletResponse, httpProp, adapterGroupVO, adapterVO, transactionProp); + // if (RESPONSE_TYPE_ASYNC.equals(responseType)) { // table의 값이 ASYNC 로 들어가 있는데 response_type_async는 ASYN 로 되어 있어 아래처럼 비교함 jwhong 2025 + if ("ASYNC".equals(responseType)) { + //responseEntity = ResponseEntity.ok("dummy"); // comment by jwhong + servletResponse.addHeader("traceId", responseData); // uuid를 response header에 + int httpStatus = servletResponse.getStatus(); + if (httpStatus == 200) { + // 업체별 aync response message 가 다르다. + String asyncMsgStyle = httpProp.getProperty("ASYNC_RTNMSG_TYPE", "").toUpperCase(); + String responseBody = makeResponseBodyMsg(asyncMsgStyle); + responseEntity = ResponseEntity.status(httpStatus).contentType(mediaType).body(responseBody); + // jwhong + } else { + responseEntity = ResponseEntity.status(httpStatus).contentType(mediaType).body(responseData); + } + } else { +// responseEntity = ResponseEntity.ok().contentType(mediaType).body(responseData); +// 버즈빌 포인트 적립 처리하기 위하여 정상응답이더라도 응답코드(apiRsltCd) 값이 200이 아닌 경우 처리를 위하여 수정 +// Filter에서 설정한 response status값을 responseEntity 생성시 적용 modify by lwk 2025.03.24 + int httpStatus = servletResponse.getStatus(); + if (httpStatus != 200) { + responseEntity = ResponseEntity.status(httpStatus).contentType(mediaType).body(responseData); + } else { + responseEntity = ResponseEntity.ok().contentType(mediaType).body(responseData); + } + } + } catch (HttpStatusException e) { + logger.warn("ApiAdapterController] " + adapterGroupName + "-" + adapterName + ">>" + e.getMessage()); + String errorMsg = MessageUtil.makeErrorMessageByMessageType(adptMsgType, encode, e.getCode(), + e.getMessage(), errorResponseFormat); + responseEntity = ResponseEntity.status(e.getStatus()).contentType(mediaType).body(errorMsg); + } catch (JwtAuthException e) { + logger.error(adapterGroupName + "-" + adapterName + ">>" + e.getMessage(), e); + String errorMsg = MessageUtil.makeErrorMessageByMessageType(adptMsgType, encode, e.getCode(), + e.getMessage(), errorResponseFormat); + responseEntity = ResponseEntity.status(HttpStatus.UNAUTHORIZED).contentType(mediaType).body(errorMsg); + } catch (Exception e) { + logger.error(adapterGroupName + "-" + adapterName + ">>" + e.getMessage(), e); + responseEntity = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).contentType(mediaType).body(e); + } finally { + /** + * 로깅 인터셉터에 데이터를 전달하기 위한 처리 + * 이미 거래처리가 끝나서 영향도가 없을만한 servletRequest에 Attribute로 전달 + * 추후 더 좋은방법이 생길경우 개선 요망 + */ + servletRequest.setAttribute(TransactionContextKeys.TRANSACTION_PROP, transactionProp); + } + return responseEntity; + } + + + + /** + * url에서 뒤쪽 /이후를 제거하면서 찾는다.
+ * /api/v1/public/getUserInfo.svc + * + * @param apiUri + * @return + */ + private HttpDynamicInAdapterUri findAdptUri(String apiUri, HttpDynamicInAdapterManager manager) { + if (StringUtils.isBlank(apiUri)) { + return null; + } + + for (int i = 0; i < 10; i++) { + HttpDynamicInAdapterUri adptUri = manager.getAdptUri(apiUri); + if (adptUri != null) { + return adptUri; + } + + // /api/v1/public + apiUri = StringUtils.substringBeforeLast(apiUri, "/"); + if (apiUri.length() < 4) { // /api + return null; + } + } + + return null; + } + + private void logError(HttpServletRequest request) { + InboundErrorInfoVO errorInfoVO = new InboundErrorInfoVO(); + + EAIServerManager eaiServerManager = EAIServerManager.getInstance(); + String serverName = eaiServerManager.getLocalServerName(); + String uuid = null; + StringBuffer sb = new StringBuffer(); + + String instanceid1 = serverName.substring(0, 2); + String instanceid2 = serverName.substring(serverName.length() - 2, serverName.length()); + String instid = instanceid1 + instanceid2; + uuid = instid + UUIDGenerator.getUUID(); + + String[] msgArgs = new String[1]; + msgArgs[0] = request.getRequestURI(); + + String errorCode = "RECEAIIRP010"; + String errorMsg = ExceptionUtil.make(new Exception("cat not find uri"), errorCode, msgArgs); + + errorInfoVO.setEaiSvcSno(uuid); // EAI서비스일련번호 + errorInfoVO.setAdptBwkGrpNm("HTTP_IN_NO_URI"); // 어댑터업무그룹명 + errorInfoVO.setErrCd(errorCode); // 에러코드 + errorInfoVO.setErrTxt(errorMsg); // 에러내용 + errorInfoVO.setErrTm(DatetimeUtil.getCurrentTime(new Date().getTime())); // 에러발생시각 + errorInfoVO.setErrDstcd(" "); + sb.append("Remote Addr : ").append(request.getRemoteAddr()).append("\n").append("Request URI : ") + .append(request.getRequestURI()); + errorInfoVO.setBwkDataTxt(sb.toString()); // 업무데이터내용 + errorInfoVO.setEaiSvrInstNm(serverName); // EAI서버인스턴스명 + + InboundErrorLogger.error(errorInfoVO); + } + + private String makeResponseBodyMsg(String asyncMsgStyle) { + + Map dataMap = new HashMap<>(); + dataMap.put("result", 1); + Map map = new HashMap<>(); + + switch (asyncMsgStyle) { + case "TB_SUC": + map.put("rspCode", "TB_SUC_000"); + map.put("rspMsg", "정상"); + map.put("data", dataMap); + break; + case "ONLYDATA": + map.put("data", dataMap); + map.put("success", "true"); + break; + default: + map.put("code", "200"); + map.put("data", dataMap); + map.put("message", "정상 처리 되었습니다."); + break; + } + + JSONObject json = new JSONObject(); + json.putAll(map); + + return json.toJSONString(); + } + + } \ No newline at end of file From 026f41681ee438a6dd895064cb35ee788a62fbeb Mon Sep 17 00:00:00 2001 From: 25W0075 <25W0075@P9801Z.kjbank.dom> Date: Mon, 17 Nov 2025 16:09:30 +0900 Subject: [PATCH 21/21] =?UTF-8?q?HEADER=5FNAME=5FCLIENT=5FID=20null=20chec?= =?UTF-8?q?k=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adapter/service/ApiAdapterService.java | 1325 ++++++++++------- 1 file changed, 799 insertions(+), 526 deletions(-) diff --git a/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java b/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java index 77b80b4..8540290 100644 --- a/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java +++ b/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java @@ -1,526 +1,799 @@ -package com.eactive.eai.adapter.service; - -import com.eactive.eai.adapter.AdapterGroupVO; -import com.eactive.eai.adapter.AdapterPropManager; -import com.eactive.eai.adapter.AdapterVO; -import com.eactive.eai.adapter.Keys; -import com.eactive.eai.adapter.http.HttpMemoryLogger; -import com.eactive.eai.adapter.http.HttpMethodType; -import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceSupport; -import com.eactive.eai.common.exception.ExceptionUtil; -import com.eactive.eai.common.message.MessageType; -import com.eactive.eai.common.util.CommonLib; -import com.eactive.eai.common.util.Logger; -import com.eactive.eai.inbound.action.ActionFactory; -import com.eactive.eai.inbound.action.RequestAction; -import com.eactive.eai.inbound.processor.Processor; -import com.eactive.eai.message.StandardMessageUtil; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; - -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.time.StopWatch; -import org.apache.mina.common.ByteBuffer; -import org.json.simple.JSONObject; -import org.json.simple.JSONValue; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; -import org.springframework.stereotype.Service; -import org.springframework.util.AntPathMatcher; - -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.net.URLDecoder; -import java.util.*; - -//for encrypt/decrypt jwhong -import com.eactive.eai.authserver.service.OAuth2Manager; -import com.kjbank.encrypt.exchange.crypto.AES256Cipher; -import com.kjbank.encrypt.exchange.crypto.AESCipher; -import java.nio.charset.StandardCharsets; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.ObjectOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import org.springframework.security.oauth2.provider.ClientDetails; - -@Service -public class ApiAdapterService extends HttpAdapterServiceSupport { - static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER); - - public static final String HEADER_GROUP = "HEADER_GROUP"; - // HEADER_GROUP JSON에 추가할 항목 정의, 없으면 전체 header 추가 - public static final String HEADER_KEYS = "HEADER_KEYS"; - public static final String PROPERTIES_NAME_HTTP_REQUEST_METHOD = "httpRequestMethod"; - - private static final String JSON_CONTENT_TYPE = "application/json"; - private static final String JSON_FIELD_NAME = "json-body"; - private static final String FILE_GROUP_NAME = "image-file"; - private static final String UPLOAD_ROOT_PATH = "UPLOAD_ROOT_PATH"; - - public String callApi(HttpServletRequest request, HttpServletResponse response, Properties httpProp, AdapterGroupVO adapterGroupVO, AdapterVO adapterVO, Properties transactionProp) throws Exception { - int traceLevel = 0; - - AdapterPropManager manager = null; - String adptGrpName = adapterGroupVO.getName(); - String adptName = adapterVO.getName(); - - - String urlDecodeYn = httpProp.getProperty(URL_DECODE_YN, "N"); - String encode = StringUtils.defaultIfBlank(adapterGroupVO.getMessageEncode(), "UTF-8"); - - String traceLevelTemp = httpProp.getProperty(TRACE_LEVEL, "0"); - String relayRequestHeaderKeys = httpProp.getProperty(HEADER_KEYS); - String headerGroupName = httpProp.getProperty(HEADER_GROUP); - - boolean isParameterType = false; - String message = null; - - String paramValue = null; - String adptMsgType = null; - - transactionProp.put(INBOUND_METHOD, request.getMethod()); - transactionProp.put(INBOUND_URI, request.getRequestURI()); - transactionProp.put(INBOUND_HEADER, getHeaders(request)); - if (StringUtils.equals(adapterVO.getAdapterGroupVO().getType(), Keys.TYPE_REST) - || StringUtils.equals(adapterVO.getAdapterGroupVO().getType(), Keys.TYPE_HTTP_CUSTOM)) { - // /api/v1/public/getUserInfo.svc - String extUrl = StringUtils.removeStart(request.getRequestURI(), request.getContextPath()); - transactionProp.put(INBOUND_EXTURI, extUrl); - } else { - transactionProp.put(INBOUND_EXTURI, getExtUri(request)); - } - transactionProp.put(INBOUND_CLIENT_IP, getClientIp(request)); // Client IP 추가 - transactionProp.put(Processor.REQUEST_ACTION, adapterVO.getAdapterGroupVO().getRefClass()); - transactionProp.put(API_PATH, httpProp.getProperty(API_PATH, "")); - transactionProp.put(PRE_FILTERS, httpProp.getProperty(PRE_FILTERS, "")); - transactionProp.put(POST_FILTERS, httpProp.getProperty(POST_FILTERS, "")); - transactionProp.put(PROPERTIES_NAME_HTTP_REQUEST_METHOD, request.getMethod()); - transactionProp.put(ALLOW_IP, httpProp.getProperty(ALLOW_IP, "")); - - transactionProp.put(ENC_PATHS, httpProp.getProperty(ENC_PATHS, "")); - - transactionProp.put(ENCRYPT_ALGORITHM, httpProp.getProperty(ENCRYPT_ALGORITHM, "")); //jwhong - transactionProp.put(HEADER_NAME_CLIENT_ID, getHeaders(request).get(HEADER_NAME_CLIENT_ID)); // jwhong - transactionProp.put(ENCRYPT_BASE_TYPE, httpProp.getProperty(ENCRYPT_BASE_TYPE, "")); //jwhong - //transactionProp.put(INBOUND_TOKEN, getHeaders(request).get(INBOUND_TOKEN)); // jwhong - transactionProp.put(INBOUND_TOKEN, getHeaders(request).get(INBOUND_TOKEN) != null ? getHeaders(request).get(INBOUND_TOKEN) : ""); //jwhong , null 이면 default로 "" put - - - try { - traceLevel = Integer.parseInt(traceLevelTemp); - } catch (Exception e) { - traceLevel = 0; - } - - StopWatch stopWatch = new StopWatch(); - stopWatch.start(); - - logger.debug("시작 >> encode = [" + encode + "]"); - - switch (HttpMethodType.getValue(request.getMethod())) { - case GET: - case DELETE: - isParameterType = true; - break; - case POST: - case PUT: - if (StringUtils.contains(request.getContentType(), "application/x-www-form-urlencoded")) { - isParameterType = true; - } else { - isParameterType = false; - } - break; - default: - break; - } - - if (isParameterType) { - paramValue = request.getQueryString(); - if (paramValue == null) - paramValue = ""; - if (traceLevel >= 3) { - HttpMemoryLogger.txlog(adptGrpName + adptName, - "RECV " + "[" + paramValue + "]" + CommonLib.getDumpMessage(paramValue)); - } - - // json으로 변환 - StringBuilder sb = new StringBuilder(); - sb.append("{"); - Map paramMap = assignParameterMap(request, adptGrpName, adptName, null, transactionProp); - int i = 0; - for (Map.Entry entry : paramMap.entrySet()) { - if (i > 0) { - sb.append(","); - } - sb.append("\"").append(entry.getKey()).append("\":"); - String[] values = entry.getValue(); - if (values.length > 1) { - // ["111", "222"] - sb.append("["); - for (int j = 0; j < values.length; j++) { - if (j > 0) { - sb.append(","); - } - sb.append("\"").append(JSONValue.escape(values[j])).append("\""); - } - sb.append("]"); - } else { - sb.append("\"").append(JSONValue.escape(values[0])).append("\""); - } - - i++; - } - - sb.append("}"); - - paramValue = sb.toString(); - - if (logger.isDebug()) { - logger.debug("HttpAdapterServiceRest] RECV (" + adptGrpName + ") = [" + paramValue + "]\n" - + CommonLib.getDumpMessage(paramValue.getBytes(encode))); - } - } else { - ServletInputStream sis = request.getInputStream(); - ByteBuffer bb = ByteBuffer.allocate(1024).setAutoExpand(true); - int i = 0; - byte[] cbuf = new byte[1024]; - while ((i = sis.read(cbuf, 0, 1024)) != -1) { - if (i == 1024) { - bb.put(cbuf); - } else { - byte[] tail = new byte[i]; - System.arraycopy(cbuf, 0, tail, 0, i); - bb.put(tail); - } - } - byte[] data = new byte[bb.position()]; - bb.position(0); - bb.get(data); - paramValue = new String(data, encode); - - if (traceLevel >= 3) { - HttpMemoryLogger.txlog(adptGrpName + adptName, - "RECV " + "[" + paramValue + "]" + CommonLib.getDumpMessage(data)); - } - - if (logger.isDebug()) { - logger.debug("HttpAdapterServiceRest] RECV (" + adptGrpName + ") = [" + paramValue + "]\n" - + CommonLib.getDumpMessage(data)); - } - } - - if (paramValue == null) { // parameter가 없는 경우때문에 처리 - paramValue = ""; - } - else { // jwhong decrypt - paramValue = doPreDecryption(paramValue, transactionProp); - } - - if ("Y".equals(urlDecodeYn) && isParameterType) { - message = URLDecoder.decode(paramValue); - } else { - message = paramValue; - } - - if (logger.isDebug()) { - String[] msgArgs = new String[2]; - msgArgs[0] = adptGrpName; - msgArgs[1] = message; - String resMsg = ExceptionUtil.make("RICEAIAHA005", msgArgs); - logger.debug(resMsg); - } - - - adptMsgType = adapterVO.getAdapterGroupVO().getMessageType(); -// HttpHeaders responseHeaders = new HttpHeaders(); -// responseHeaders.setContentType(MediaType.valueOf("application/json;charset=" + encode)); - - - // HEADER_GROUP 셋팅 - if (MessageType.JSON.equals(adptMsgType) && StringUtils.isNotBlank(headerGroupName) - && StringUtils.isNotBlank(relayRequestHeaderKeys)) { - JSONObject jsonMessage = (JSONObject) JSONValue.parse(message); - JSONObject headerJson = new JSONObject(); - if (StringUtils.equalsIgnoreCase(relayRequestHeaderKeys, "ALL")) { - for (Enumeration e = request.getHeaderNames(); e.hasMoreElements(); ) { - String key = e.nextElement(); - headerJson.put(key, request.getHeader(key)); - } - } else { - String[] relayKeyArr = org.springframework.util.StringUtils - .tokenizeToStringArray(relayRequestHeaderKeys, ","); - - for (String key : relayKeyArr) { - String headerValue = request.getHeader(key); - if (StringUtils.isNotBlank(headerValue)) { - headerJson.put(key, headerValue); - } - } - } - - if (headerJson.size() > 0) { - jsonMessage.put(headerGroupName, headerJson); - message = jsonMessage.toJSONString(); - } - } - - if (message == null) { - message = ""; - } - - transactionProp.put(INBOUND_REQUEST_MESSAGE, message); - // 로컬 서비스 호출 ,encoding 처리 추가 - String result = (String) service(adptGrpName, adptName, message, transactionProp, request, response); - - if (logger.isDebug()) { - logger.debug("HttpAdapterServiceRest] result " + encode + " (" + adptGrpName + ") = [" + result + "]"); - } - - stopWatch.stop(); - - String syncAsyncType = transactionProp.getProperty(INBOUND_SYNC_ASYNC_TYPE); - if (!"ASYN".equals(syncAsyncType) && MessageType.JSON.equals(adptMsgType) && StringUtils.isNotBlank(headerGroupName)) { - ObjectMapper mapper = new ObjectMapper(); - ObjectNode rootNode = (ObjectNode) mapper.readTree(result); - JsonNode headerGroup = rootNode.get(headerGroupName); - if(headerGroup != null) { - for(Iterator it = headerGroup.fieldNames(); it.hasNext();) { - String name = it.next(); - String value = headerGroup.get(name).asText(); - response.addHeader(name, value); - } - rootNode.remove(headerGroupName); - result = mapper.writeValueAsString(rootNode); - } - } - - return result; - } - - - // jwhong encrypt - - private String doPreDecryption(String eaiBody, Properties transactionProp) { - String decryptAlgorithm = transactionProp.getProperty(ENCRYPT_ALGORITHM, ""); - String xElinkClientId = transactionProp.getProperty(HEADER_NAME_CLIENT_ID, ""); // 이 값이 OAuth의 client id 값이다 . http header 에 포함되어 온다. jwhong - String encryptBaseKeyType = transactionProp.getProperty(ENCRYPT_BASE_TYPE); - String inboundToken = transactionProp.getProperty(INBOUND_TOKEN, ""); - - if ( decryptAlgorithm == "" ) { // 복호화 대상이 아님 - return eaiBody; - } - - // 암호화 key를 token 내용으로 할지 client secret 내용으로 할지 결정함. adapter property에 정의함 - // ENCRYPT_ALGORITHM 을 설정했는데 ENCRYPT_BASE_TYPE을 설정안하면 Decrypt 수행시 Exception 발생함 - String clientSecret = ""; - if ("TOKEN".equalsIgnoreCase(encryptBaseKeyType)) { - clientSecret = inboundToken; - } else if ( "SECRETKEY".equalsIgnoreCase(encryptBaseKeyType)) { - OAuth2Manager manager = OAuth2Manager.getInstance(); - ClientDetails clientDetail = manager.getClientDeatilsStore().get(xElinkClientId); - - if ( clientDetail != null ) { - clientSecret = clientDetail.getClientSecret(); - } - } - - byte[] decryptedMessage = null; - decryptedMessage = doInboundPreDecrypt(eaiBody, decryptAlgorithm,clientSecret); - - String resultMessage = new String(decryptedMessage, StandardCharsets.UTF_8 ); - return resultMessage; - //return new String(decryptedMessage, StandardCharsets.UTF_8 ); - } - - - private byte[] convertObjectToBytes(Object obj) throws IOException { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(bos); - oos.writeObject(obj); - oos.flush(); - return bos.toByteArray(); - } - - private byte[] convertObjectToBase64Bytes(Object obj) throws IOException { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(bos); - oos.writeObject(obj); - oos.flush(); - oos.close(); - - // 직렬화된 byte[] → Base64 문자열 → 다시 byte[]로 변환 - String base64String = Base64.getEncoder().encodeToString(bos.toByteArray()); - return base64String.getBytes(StandardCharsets.UTF_8); - } - - public static Object convertBytesToObject(byte[] bytes) throws IOException, ClassNotFoundException { - try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes); - ObjectInputStream ois = new ObjectInputStream(bis)) { - return ois.readObject(); - } - } - - - private byte[] doInboundPreDecrypt(String eaiStringBody, String decryptAlgorithm, String clientSecretKey) { - - byte[] decryptedMessage = null; - //String eaiStringBody = new String(eaiBody, StandardCharsets.UTF_8); - - //test source - //System.out.println("eaiBody 바이트 배열 길이: " + eaiBody.length); - System.out.println("Base64 문자열: " + eaiStringBody); - System.out.println("Base64 문자열 길이: " + eaiStringBody.length()); - System.out.println("Base64 문자열 끝: " + eaiStringBody.substring(eaiStringBody.length() - 10)); - - // Base64 디코딩 테스트 - try { - byte[] decoded = Base64.getDecoder().decode(eaiStringBody); - System.out.println("디코딩 성공, 길이: " + decoded.length); - } catch (IllegalArgumentException e) { - System.out.println("Base64 디코딩 실패: " + e.getMessage()); - } - // end test source - - switch (decryptAlgorithm) { - case "AES128": - - String key128 = clientSecretKey.substring(22,38); //togetherEncoder 경우는 substring(44,60) 이네?? - try { - //String decryptedStrMessage = AESCipher.decrypt(eaiStringBody, key128); - String decryptedStrMessage = AESCipher.decryptExistException(eaiStringBody, key128); - decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); - } catch (Exception e) { - e.printStackTrace(); - logger.error("HttpClientAdapterServiceRest] AES128 Decryption error=" + e.getMessage()); - } - break; - case "AES256": - String key = clientSecretKey.substring(10,42); - try { - String decryptedStrMessage = AES256Cipher.decrypt(eaiStringBody, key); - decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); - } catch (Exception e) { - e.printStackTrace(); - logger.error("HttpClientAdapterServiceRest] AES256 Decryption error=" + e.getMessage()); - } - break; - default: - try { - //decryptedMessage = Arrays.copyOf(eaiBody, eaiBody.length); - decryptedMessage = eaiStringBody.getBytes(); - } catch (Exception e) { - e.printStackTrace(); - logger.error("HttpClientAdapterServiceRest] doOutboundPostFilter Array copy error=" + e.getMessage()); - } - break; - } - - return decryptedMessage; - } - - // jwhong until here - - - private Map assignParameterMap(HttpServletRequest request, String adptGrpName, String adptName, - Object requestBytes, Properties prop) { - // PathVariable 체크 - if (StringUtils.equalsAnyIgnoreCase(request.getMethod(), HttpMethod.GET.name(), HttpMethod.DELETE.name()) - && StringUtils.isBlank(request.getQueryString())) { - try { - String actionName = prop.getProperty(Processor.REQUEST_ACTION); - RequestAction action = ActionFactory.createAction(actionName); - action.setAdapterInfo(adptGrpName, adptName, prop); - String[] keys = action.perform(requestBytes); - String requestPath = keys[0]; - - // PathVariable 지원 추가 - String ruledPath = StandardMessageUtil.getMatchedKey(requestPath, actionName); - if (!StringUtils.equals(requestPath, ruledPath) && StringUtils.contains(ruledPath, "{")) { - Map paramMap = new AntPathMatcher().extractUriTemplateVariables(ruledPath, - requestPath); - if (paramMap != null && paramMap.size() > 0) { - Map returnMap = new HashMap<>(); - for (String key : paramMap.keySet()) { - if (StringUtils.equalsIgnoreCase(key, "method")) { - continue; - } - returnMap.put(key, new String[] { paramMap.get(key) }); - } - - return returnMap; - } - } - } catch (Exception e) { - logger.error(e.getMessage()); - } - } - - return request.getParameterMap(); - } - - private Properties getHeaders(HttpServletRequest request) { - Properties prop = new Properties(); - - Enumeration headerNames = request.getHeaderNames(); - while (headerNames.hasMoreElements()) { - String key = headerNames.nextElement(); - String value = request.getHeader(key); - prop.setProperty(key, value); - } - - return prop; - } - - private String getExtUri(HttpServletRequest request) { - String orgUri = request.getRequestURI().replaceAll(request.getContextPath(), ""); - String uri = getExtUri(orgUri, 3); - if (uri != null && uri.trim().length() > 0) { - return "/" + uri; - } else { - return ""; - } - } - - private static String getExtUri(String url, int length) { - String[] urls = url.split("/"); - List newUrls = new ArrayList<>(); - Collections.addAll(newUrls, urls); - return StringUtils.join(newUrls.subList(length, urls.length).toArray(), "/"); - } - - @Override - @Deprecated - public void service(String adptGrpName, String adptName, HttpServletRequest request, HttpServletResponse response) { - - } - - /** - * HTTP 요청에서 클라이언트 IP를 추출합니다. - * X-Forwarded-For 헤더가 있는 경우 이를 우선적으로 사용하고, - * 없는 경우 remoteAddr을 사용합니다. - */ - private String getClientIp(HttpServletRequest request) { - String ipAddress = request.getHeader("X-Forwarded-For"); - if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { - ipAddress = request.getHeader("Proxy-Client-IP"); - } - if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { - ipAddress = request.getHeader("WL-Proxy-Client-IP"); - } - if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { - ipAddress = request.getHeader("HTTP_CLIENT_IP"); - } - if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { - ipAddress = request.getHeader("HTTP_X_FORWARDED_FOR"); - } - if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { - ipAddress = request.getRemoteAddr(); - } - return ipAddress; - } -} +package com.eactive.eai.adapter.service; + +import com.eactive.eai.adapter.AdapterGroupVO; +import com.eactive.eai.adapter.AdapterPropManager; +import com.eactive.eai.adapter.AdapterVO; +import com.eactive.eai.adapter.Keys; +import com.eactive.eai.adapter.http.HttpMemoryLogger; +import com.eactive.eai.adapter.http.HttpMethodType; +import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceSupport; +import com.eactive.eai.adapter.http.dynamic.filter.JwtAuthFilter; +import com.eactive.eai.common.exception.ExceptionUtil; +import com.eactive.eai.common.message.MessageType; +import com.eactive.eai.common.util.CommonLib; +import com.eactive.eai.common.util.Logger; +import com.eactive.eai.inbound.action.ActionFactory; +import com.eactive.eai.inbound.action.RequestAction; +import com.eactive.eai.inbound.processor.Processor; +import com.eactive.eai.message.StandardMessageUtil; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.time.StopWatch; +import org.apache.mina.common.ByteBuffer; +import org.json.simple.JSONObject; +import org.json.simple.JSONValue; +import org.json.simple.parser.JSONParser; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Service; +import org.springframework.util.AntPathMatcher; + +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.net.URLDecoder; +import java.util.*; + +//for encrypt/decrypt jwhong +import com.eactive.eai.authserver.service.OAuth2Manager; +import com.kjbank.encrypt.exchange.crypto.AES256Cipher; +import com.kjbank.encrypt.exchange.crypto.AESCipher; +import com.kjbank.encrypt.exchange.crypto.AES256GCMCipher; +import java.nio.charset.StandardCharsets; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import org.springframework.security.oauth2.provider.ClientDetails; +import com.nimbusds.jwt.SignedJWT; + + +@Service +public class ApiAdapterService extends HttpAdapterServiceSupport { + static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER); + + public static final String HEADER_GROUP = "HEADER_GROUP"; + public static final String HTTP_STATUS = "HTTP_STATUS"; // jwhong + // HEADER_GROUP JSON에 추가할 항목 정의, 없으면 전체 header 추가 + public static final String HEADER_KEYS = "HEADER_KEYS"; + public static final String PROPERTIES_NAME_HTTP_REQUEST_METHOD = "httpRequestMethod"; + + private static final String JSON_CONTENT_TYPE = "application/json"; + private static final String JSON_FIELD_NAME = "json-body"; + private static final String FILE_GROUP_NAME = "image-file"; + private static final String UPLOAD_ROOT_PATH = "UPLOAD_ROOT_PATH"; + public static final String PAYLOAD_PARAM_NAME_CLIENT_ID = "client_id"; // jwhong + + public String callApi(HttpServletRequest request, HttpServletResponse response, Properties httpProp, AdapterGroupVO adapterGroupVO, AdapterVO adapterVO, Properties transactionProp) throws Exception { + int traceLevel = 0; + + AdapterPropManager manager = null; + String adptGrpName = adapterGroupVO.getName(); + String adptName = adapterVO.getName(); + + + String urlDecodeYn = httpProp.getProperty(URL_DECODE_YN, "N"); + String encode = StringUtils.defaultIfBlank(adapterGroupVO.getMessageEncode(), "UTF-8"); + + String traceLevelTemp = httpProp.getProperty(TRACE_LEVEL, "0"); + String relayRequestHeaderKeys = httpProp.getProperty(HEADER_KEYS); + String headerGroupName = httpProp.getProperty(HEADER_GROUP); + + boolean isParameterType = false; + String message = null; + + String paramValue = null; + String adptMsgType = null; + + transactionProp.put(INBOUND_METHOD, request.getMethod()); + transactionProp.put(INBOUND_URI, request.getRequestURI()); + transactionProp.put(INBOUND_HEADER, getHeaders(request)); + if (StringUtils.equals(adapterVO.getAdapterGroupVO().getType(), Keys.TYPE_REST) + || StringUtils.equals(adapterVO.getAdapterGroupVO().getType(), Keys.TYPE_HTTP_CUSTOM)) { + // /api/v1/public/getUserInfo.svc + String extUrl = StringUtils.removeStart(request.getRequestURI(), request.getContextPath()); + transactionProp.put(INBOUND_EXTURI, extUrl); + } else { + transactionProp.put(INBOUND_EXTURI, getExtUri(request)); + } + transactionProp.put(INBOUND_CLIENT_IP, getClientIp(request)); // Client IP 추가 + transactionProp.put(Processor.REQUEST_ACTION, adapterVO.getAdapterGroupVO().getRefClass()); + transactionProp.put(API_PATH, httpProp.getProperty(API_PATH, "")); + transactionProp.put(PRE_FILTERS, httpProp.getProperty(PRE_FILTERS, "")); + transactionProp.put(POST_FILTERS, httpProp.getProperty(POST_FILTERS, "")); + transactionProp.put(PROPERTIES_NAME_HTTP_REQUEST_METHOD, request.getMethod()); + transactionProp.put(ALLOW_IP, httpProp.getProperty(ALLOW_IP, "")); + + transactionProp.put(ENC_PATHS, httpProp.getProperty(ENC_PATHS, "")); + + transactionProp.put(ENCRYPT_ALGORITHM, httpProp.getProperty(ENCRYPT_ALGORITHM, "")); //jwhong + if (getHeaders(request).get(HEADER_NAME_CLIENT_ID) != null) { // jwhong + transactionProp.put(HEADER_NAME_CLIENT_ID, getHeaders(request).get(HEADER_NAME_CLIENT_ID)); + } + transactionProp.put(ENCRYPT_BASE_TYPE, httpProp.getProperty(ENCRYPT_BASE_TYPE, "")); //jwhong + //transactionProp.put(INBOUND_TOKEN, getHeaders(request).get(INBOUND_TOKEN)); // jwhong + transactionProp.put(INBOUND_TOKEN, getHeaders(request).get(INBOUND_TOKEN) != null ? getHeaders(request).get(INBOUND_TOKEN) : ""); //jwhong , null 이면 default로 "" put + transactionProp.put(ENCRYPT_AES256_IV, httpProp.getProperty(ENCRYPT_AES256_IV, "")); //jwhong + transactionProp.put(ENCRYPT_AES256_KEY, httpProp.getProperty(ENCRYPT_AES256_KEY, "")); //jwhong + + + try { + traceLevel = Integer.parseInt(traceLevelTemp); + } catch (Exception e) { + traceLevel = 0; + } + + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + + logger.debug("시작 >> encode = [" + encode + "]"); + + switch (HttpMethodType.getValue(request.getMethod())) { + case GET: + case DELETE: + isParameterType = true; + break; + case POST: + case PUT: + if (StringUtils.contains(request.getContentType(), "application/x-www-form-urlencoded")) { + isParameterType = true; + } else { + isParameterType = false; + } + break; + default: + break; + } + + if (isParameterType) { + paramValue = request.getQueryString(); + if (paramValue == null) + paramValue = ""; + if (traceLevel >= 3) { + HttpMemoryLogger.txlog(adptGrpName + adptName, + "RECV " + "[" + paramValue + "]" + CommonLib.getDumpMessage(paramValue)); + } + + // json으로 변환 + StringBuilder sb = new StringBuilder(); + sb.append("{"); + Map paramMap = assignParameterMap(request, adptGrpName, adptName, null, transactionProp); + int i = 0; + for (Map.Entry entry : paramMap.entrySet()) { + if (i > 0) { + sb.append(","); + } + sb.append("\"").append(entry.getKey()).append("\":"); + String[] values = entry.getValue(); + if (values.length > 1) { + // ["111", "222"] + sb.append("["); + for (int j = 0; j < values.length; j++) { + if (j > 0) { + sb.append(","); + } + sb.append("\"").append(JSONValue.escape(values[j])).append("\""); + } + sb.append("]"); + } else { + sb.append("\"").append(JSONValue.escape(values[0])).append("\""); + } + + i++; + } + + sb.append("}"); + + paramValue = sb.toString(); + + if (logger.isDebug()) { + logger.debug("HttpAdapterServiceRest] RECV (" + adptGrpName + ") = [" + paramValue + "]\n" + + CommonLib.getDumpMessage(paramValue.getBytes(encode))); + } + } else { + ServletInputStream sis = request.getInputStream(); + ByteBuffer bb = ByteBuffer.allocate(1024).setAutoExpand(true); + int i = 0; + byte[] cbuf = new byte[1024]; + while ((i = sis.read(cbuf, 0, 1024)) != -1) { + if (i == 1024) { + bb.put(cbuf); + } else { + byte[] tail = new byte[i]; + System.arraycopy(cbuf, 0, tail, 0, i); + bb.put(tail); + } + } + byte[] data = new byte[bb.position()]; + bb.position(0); + bb.get(data); + paramValue = new String(data, encode); + + if (traceLevel >= 3) { + HttpMemoryLogger.txlog(adptGrpName + adptName, + "RECV " + "[" + paramValue + "]" + CommonLib.getDumpMessage(data)); + } + + if (logger.isDebug()) { + logger.debug("HttpAdapterServiceRest] RECV (" + adptGrpName + ") = [" + paramValue + "]\n" + + CommonLib.getDumpMessage(data)); + } + } + + if (paramValue == null) { // parameter가 없는 경우때문에 처리 + paramValue = ""; + } + else { // jwhong decrypt + paramValue = doPreDecryption(paramValue, transactionProp, request); + } + + if ("Y".equals(urlDecodeYn) && isParameterType) { + message = URLDecoder.decode(paramValue); + } else { + message = paramValue; + } + + if (logger.isDebug()) { + String[] msgArgs = new String[2]; + msgArgs[0] = adptGrpName; + msgArgs[1] = message; + String resMsg = ExceptionUtil.make("RICEAIAHA005", msgArgs); + logger.debug(resMsg); + } + + + adptMsgType = adapterVO.getAdapterGroupVO().getMessageType(); +// HttpHeaders responseHeaders = new HttpHeaders(); +// responseHeaders.setContentType(MediaType.valueOf("application/json;charset=" + encode)); + + + // HEADER_GROUP 셋팅 + if (MessageType.JSON.equals(adptMsgType) && StringUtils.isNotBlank(headerGroupName) + && StringUtils.isNotBlank(relayRequestHeaderKeys)) { + JSONObject jsonMessage = (JSONObject) JSONValue.parse(message); + JSONObject headerJson = new JSONObject(); + if (StringUtils.equalsIgnoreCase(relayRequestHeaderKeys, "ALL")) { + for (Enumeration e = request.getHeaderNames(); e.hasMoreElements(); ) { + String key = e.nextElement(); + headerJson.put(key, request.getHeader(key)); + } + } else { + String[] relayKeyArr = org.springframework.util.StringUtils + .tokenizeToStringArray(relayRequestHeaderKeys, ","); + + for (String key : relayKeyArr) { + String headerValue = request.getHeader(key); + if (StringUtils.isNotBlank(headerValue)) { + headerJson.put(key, headerValue); + } + } + } + + if (headerJson.size() > 0) { + jsonMessage.put(headerGroupName, headerJson); + message = jsonMessage.toJSONString(); + } + } + + if (message == null) { + message = ""; + } + + transactionProp.put(INBOUND_REQUEST_MESSAGE, message); + // 로컬 서비스 호출 ,encoding 처리 추가 + String result = (String) service(adptGrpName, adptName, message, transactionProp, request, response); + + if (logger.isDebug()) { + logger.debug("HttpAdapterServiceRest] result " + encode + " (" + adptGrpName + ") = [" + result + "]"); + } + + stopWatch.stop(); + + String syncAsyncType = transactionProp.getProperty(INBOUND_SYNC_ASYNC_TYPE); + + if (!"ASYN".equals(syncAsyncType) && MessageType.JSON.equals(adptMsgType) && StringUtils.isNotBlank(headerGroupName)) { + ObjectMapper mapper = new ObjectMapper(); + ObjectNode rootNode = (ObjectNode) mapper.readTree(result); + JsonNode headerGroup = rootNode.get(headerGroupName); + if(headerGroup != null) { + for(Iterator it = headerGroup.fieldNames(); it.hasNext();) { + String name = it.next(); + String value = headerGroup.get(name).asText(); + response.addHeader(name, value); + } + rootNode.remove(headerGroupName); + result = mapper.writeValueAsString(rootNode); + } + } + + // KJBank는 요청에 대한 응답 (Sync응답, Aync 에 대한 Ack응답) 에 대하여 암호화 하지 않는다. 무조건 안한다. 따라서 아래부분은 구현은 했지만 사용하지 않는다. + //result = doPostEncryption(result, transactionProp); // jwhong Encrypt + return result; + } + + + // jwhong decrypt + + private String doPreDecryption(String eaiBody, Properties transactionProp, HttpServletRequest request) { + String decryptAlgorithm = transactionProp.getProperty(ENCRYPT_ALGORITHM, ""); + String xElinkClientId = transactionProp.getProperty(HEADER_NAME_CLIENT_ID, ""); // 이 값이 OAuth의 client id 값이다 . http header 에 포함되어 온다. jwhong + String encryptBaseKeyType = transactionProp.getProperty(ENCRYPT_BASE_TYPE); + //String inboundToken2 = transactionProp.getProperty(INBOUND_TOKEN, ""); // 이건 token 값이 아니고 authorization 값이다 + String inboundToken = ""; + + String secretAES256Iv = transactionProp.getProperty("ENCRYPT_AES256_IV"); + String secretAES256Key = transactionProp.getProperty("ENCRYPT_AES256_KEY"); + + if ( decryptAlgorithm == "" ) { // 복호화 대상이 아님 + return eaiBody; + } + + inboundToken = JwtTokenExtractor(request); + xElinkClientId = JwtClientIdExtractor(inboundToken); // token에서 client id를 추출함 + + // 암호화 key를 token 내용으로 할지 client secret 내용으로 할지 결정함. adapter property에 정의함 + // ENCRYPT_ALGORITHM 을 설정했는데 ENCRYPT_BASE_TYPE을 설정안하면 Decrypt 수행시 Exception 발생함 + String clientSecret = ""; + if ("TOKEN".equalsIgnoreCase(encryptBaseKeyType)) { + clientSecret = inboundToken; + } else if ( "SECRETKEY".equalsIgnoreCase(encryptBaseKeyType)) { + OAuth2Manager manager = OAuth2Manager.getInstance(); + ClientDetails clientDetail = manager.getClientDeatilsStore().get(xElinkClientId); + + if ( clientDetail != null ) { // 여기서 not null 이라는 것은 apim oauth server에서 발급된 token 임. + // 즉 KJBank 에서 요청이 들어온 것이다. + clientSecret = clientDetail.getClientSecret(); + } // 그럼 업체에서 요청이 들어오면?? 업체도 apim oauth server에서 발급된 token을 사용하는것이다. + } + + byte[] decryptedMessage = null; + decryptedMessage = doInboundPreDecrypt(eaiBody, decryptAlgorithm,clientSecret,secretAES256Iv, secretAES256Key ); + + String resultMessage = new String(decryptedMessage, StandardCharsets.UTF_8 ); + return resultMessage; + //return new String(decryptedMessage, StandardCharsets.UTF_8 ); + } + + + // jwhong encrypt + private String doPostEncryption(String eaiBody, Properties transactionProp) { + String decryptAlgorithm = transactionProp.getProperty(ENCRYPT_ALGORITHM, ""); + String xElinkClientId = transactionProp.getProperty(HEADER_NAME_CLIENT_ID, ""); // 이 값이 OAuth의 client id 값이다 . http header 에 포함되어 온다. jwhong + String encryptBaseKeyType = transactionProp.getProperty(ENCRYPT_BASE_TYPE); + String inboundToken = transactionProp.getProperty(INBOUND_TOKEN, ""); + + String secretAES256Iv = transactionProp.getProperty("ENCRYPT_AES256_IV"); + String secretAES256Key = transactionProp.getProperty("ENCRYPT_AES256_KEY"); + + + if ( decryptAlgorithm == "" ) { // 복호화 대상이 아님 + return eaiBody; + } + + // 암호화 key를 token 내용으로 할지 client secret 내용으로 할지 결정함. adapter property에 정의함 + // ENCRYPT_ALGORITHM 을 설정했는데 ENCRYPT_BASE_TYPE을 설정안하면 Decrypt 수행시 Exception 발생함 + String clientSecret = ""; + if ("TOKEN".equalsIgnoreCase(encryptBaseKeyType)) { + clientSecret = inboundToken; + } else if ( "SECRETKEY".equalsIgnoreCase(encryptBaseKeyType)) { + OAuth2Manager manager = OAuth2Manager.getInstance(); + ClientDetails clientDetail = manager.getClientDeatilsStore().get(xElinkClientId); + + if ( clientDetail != null ) { + clientSecret = clientDetail.getClientSecret(); + } + } + + byte[] decryptedMessage = null; + decryptedMessage = doInboundPostEncrypt(eaiBody, decryptAlgorithm,clientSecret,secretAES256Iv, secretAES256Key ); + + String resultMessage = new String(decryptedMessage, StandardCharsets.UTF_8 ); + return resultMessage; + //return new String(decryptedMessage, StandardCharsets.UTF_8 ); + } + + + private byte[] convertObjectToBytes(Object obj) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(obj); + oos.flush(); + return bos.toByteArray(); + } + + private byte[] convertObjectToBase64Bytes(Object obj) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + oos.writeObject(obj); + oos.flush(); + oos.close(); + + // 직렬화된 byte[] → Base64 문자열 → 다시 byte[]로 변환 + String base64String = Base64.getEncoder().encodeToString(bos.toByteArray()); + return base64String.getBytes(StandardCharsets.UTF_8); + } + + public static Object convertBytesToObject(byte[] bytes) throws IOException, ClassNotFoundException { + try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bis)) { + return ois.readObject(); + } + } + + + private byte[] doInboundPreDecrypt(String eaiStringBody, String decryptAlgorithm, String clientSecretKey, String secretAES256Iv, String secretAES256Key) { + + byte[] decryptedMessage = null; + //String eaiStringBody = new String(eaiBody, StandardCharsets.UTF_8); + + eaiStringBody = extractBodyMsg(decryptAlgorithm, eaiStringBody); + + //test source + //System.out.println("eaiBody 바이트 배열 길이: " + eaiBody.length); + System.out.println("Base64 문자열: " + eaiStringBody); + System.out.println("Base64 문자열 길이: " + eaiStringBody.length()); + System.out.println("Base64 문자열 끝: " + eaiStringBody.substring(eaiStringBody.length() - 10)); + + // Base64 디코딩 테스트 + try { + byte[] decoded = Base64.getDecoder().decode(eaiStringBody); + System.out.println("디코딩 성공, 길이: " + decoded.length); + } catch (IllegalArgumentException e) { + System.out.println("Base64 디코딩 실패: " + e.getMessage()); + } + // end test source + + switch (decryptAlgorithm) { + case "AES128-TOSS": + try { + String key128 = clientSecretKey.substring(22,38); //togetherEncoder 경우는 substring(44,60) 이네?? + //String decryptedStrMessage = AESCipher.decrypt(eaiStringBody, key128); + String decryptedStrMessage = AESCipher.decryptExistException(eaiStringBody, key128); + decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES128 Decryption error=" + e.getMessage()); + } + break; + case "AES128-TOGETHER": + try { + String key128 = clientSecretKey.substring(44,60); //togetherEncoder 경우는 substring(44,60) 이네?? + //String decryptedStrMessage = AESCipher.decrypt(eaiStringBody, key128); + String decryptedStrMessage = AESCipher.decryptExistException(eaiStringBody, key128); + decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES128 Decryption error=" + e.getMessage()); + } + break; + case "AES256": + try { + String key = clientSecretKey.substring(10,42); + String decryptedStrMessage = AES256Cipher.decrypt(eaiStringBody, key); + decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES256 Decryption error=" + e.getMessage()); + } + break; + case "AES256-KAKAO": + try { + String decryptedStrMessage = AES256Cipher.decrypt(eaiStringBody, secretAES256Iv, secretAES256Key); + decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES256 Decryption error=" + e.getMessage()); + } + break; + case "AES256-TOSS": + try { + String decryptedStrMessage = AES256Cipher.decrypt(eaiStringBody, secretAES256Iv, secretAES256Key); + decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES256 Decryption error=" + e.getMessage()); + } + break; + + case "AES256GCM": + try { + byte[] key = AES256GCMCipher.generateKey(); + AES256GCMCipher cipher = new AES256GCMCipher(key); + byte[] aad = "metadata".getBytes(); + + String decryptedStrMessage = cipher.decrypt(eaiStringBody , aad); + decryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES256GCM Encryption error=" + e.getMessage()); + } + break; + default: + try { + decryptedMessage = eaiStringBody.getBytes(); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] doOutboundPostFilter Array copy error=" + e.getMessage()); + } + break; + } + + return decryptedMessage; + } + + private String extractBodyMsg(String decryptAlgorithm, String eaiStringBody) { + + String decryptedJsonKey = ""; + String decryptedBodyMessage = ""; + + switch (decryptAlgorithm) { + case "AES128-TOSS": + decryptedJsonKey = "preScreeningRequest"; + break; + case "AES128-TOGETHER": + decryptedJsonKey = "obpTxData"; + break; + case "AES256": + decryptedJsonKey = "preScreeningRequest"; + break; + case "AES256-KAKAO": + decryptedJsonKey = "encrypted_data"; + break; + case "AES256-TOSS": + decryptedJsonKey = "encryptedData"; + break; + case "AES256GCM": + break; + default: + break; + } + + try { + JSONParser parser = new JSONParser(); + JSONObject jsonObject = (JSONObject) parser.parse(eaiStringBody); + decryptedBodyMessage = (String) jsonObject.get(decryptedJsonKey); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClient5AdapterServiceRest] extractBodyMsg error : " + e.getMessage()); + } + + return decryptedBodyMessage; + + } + + private byte[] doInboundPostEncrypt(String eaiStringBody, String encryptAlgorithm, String clientSecretKey, String secretAES256Iv, String secretAES256Key) { + + byte[] encryptedMessage = null; + //String eaiStringBody = new String(eaiBody, StandardCharsets.UTF_8); + + //test source + //System.out.println("eaiBody 바이트 배열 길이: " + eaiBody.length); + System.out.println("Base64 문자열: " + eaiStringBody); + System.out.println("Base64 문자열 길이: " + eaiStringBody.length()); + System.out.println("Base64 문자열 끝: " + eaiStringBody.substring(eaiStringBody.length() - 10)); + + // Base64 디코딩 테스트 + try { + byte[] decoded = Base64.getDecoder().decode(eaiStringBody); + System.out.println("디코딩 성공, 길이: " + decoded.length); + } catch (IllegalArgumentException e) { + System.out.println("Base64 디코딩 실패: " + e.getMessage()); + } + // end test source + + switch (encryptAlgorithm) { + case "AES128-TOSS": + try { + String key128 = clientSecretKey.substring(22,38); //togetherEncoder 경우는 substring(44,60) 이네?? + String decryptedStrMessage = AESCipher.encrypt(eaiStringBody, key128); + encryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES128 Decryption error=" + e.getMessage()); + } + break; + case "AES128-TOGETHER": + try { + String key128 = clientSecretKey.substring(44,60); //togetherEncoder 경우는 substring(44,60) 이네?? + String decryptedStrMessage = AESCipher.encrypt(eaiStringBody, key128); + encryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES128 Decryption error=" + e.getMessage()); + } + break; + case "AES256": + try { + String key = clientSecretKey.substring(10,42); + String decryptedStrMessage = AES256Cipher.encrypt(eaiStringBody, key); + encryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES256 Decryption error=" + e.getMessage()); + } + break; + case "AES256-KAKAO": + try { + String decryptedStrMessage = AES256Cipher.encrypt(eaiStringBody, secretAES256Iv, secretAES256Key); + encryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES256 Decryption error=" + e.getMessage()); + } + break; + case "AES256-TOSS": + try { + String decryptedStrMessage = AES256Cipher.encrypt(eaiStringBody, secretAES256Iv, secretAES256Key); + encryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES256 Decryption error=" + e.getMessage()); + } + break; + + case "AES256GCM": + try { + byte[] key = AES256GCMCipher.generateKey(); + AES256GCMCipher cipher = new AES256GCMCipher(key); + byte[] aad = "metadata".getBytes(); + + String decryptedStrMessage = cipher.encrypt(eaiStringBody , aad); + encryptedMessage = decryptedStrMessage.getBytes(StandardCharsets.UTF_8); + + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] AES256GCM Encryption error=" + e.getMessage()); + } + break; + default: + try { + encryptedMessage = eaiStringBody.getBytes(); + } catch (Exception e) { + e.printStackTrace(); + logger.error("HttpClientAdapterServiceRest] doOutboundPostFilter Array copy error=" + e.getMessage()); + } + break; + } + + return encryptedMessage; + } + + + + private String JwtTokenExtractor(HttpServletRequest request) { + + String Token = ""; + try { + Token = JwtAuthFilter.extractJWTToken(request); + } catch (Exception e) { + logger.error(e.getMessage()); + } + + System.out.println("Token is: " + Token); + return Token; + + } + + private String JwtClientIdExtractor(String inboundToken) { + + String tokenClientId =""; + try { + SignedJWT signedJWT = SignedJWT.parse(inboundToken); + tokenClientId = (String) signedJWT.getJWTClaimsSet().getClaim(PAYLOAD_PARAM_NAME_CLIENT_ID); + } catch (Exception e) { + logger.error(e.getMessage()); + tokenClientId = ""; + } + + System.out.println("Token Client ID: " + tokenClientId); + return tokenClientId; + + } + + // jwhong until here + + + private Map assignParameterMap(HttpServletRequest request, String adptGrpName, String adptName, + Object requestBytes, Properties prop) { + // PathVariable 체크 + if (StringUtils.equalsAnyIgnoreCase(request.getMethod(), HttpMethod.GET.name(), HttpMethod.DELETE.name()) + && StringUtils.isBlank(request.getQueryString())) { + try { + String actionName = prop.getProperty(Processor.REQUEST_ACTION); + RequestAction action = ActionFactory.createAction(actionName); + action.setAdapterInfo(adptGrpName, adptName, prop); + String[] keys = action.perform(requestBytes); + String requestPath = keys[0]; + + // PathVariable 지원 추가 + String ruledPath = StandardMessageUtil.getMatchedKey(requestPath, actionName); + if (!StringUtils.equals(requestPath, ruledPath) && StringUtils.contains(ruledPath, "{")) { + Map paramMap = new AntPathMatcher().extractUriTemplateVariables(ruledPath, + requestPath); + if (paramMap != null && paramMap.size() > 0) { + Map returnMap = new HashMap<>(); + for (String key : paramMap.keySet()) { + if (StringUtils.equalsIgnoreCase(key, "method")) { + continue; + } + returnMap.put(key, new String[] { paramMap.get(key) }); + } + + return returnMap; + } + } + } catch (Exception e) { + logger.error(e.getMessage()); + } + } + + return request.getParameterMap(); + } + + private Properties getHeaders(HttpServletRequest request) { + Properties prop = new Properties(); + + Enumeration headerNames = request.getHeaderNames(); + while (headerNames.hasMoreElements()) { + String key = headerNames.nextElement(); + String value = request.getHeader(key); + prop.setProperty(key, value); + } + + return prop; + } + + private String getExtUri(HttpServletRequest request) { + String orgUri = request.getRequestURI().replaceAll(request.getContextPath(), ""); + String uri = getExtUri(orgUri, 3); + if (uri != null && uri.trim().length() > 0) { + return "/" + uri; + } else { + return ""; + } + } + + private static String getExtUri(String url, int length) { + String[] urls = url.split("/"); + List newUrls = new ArrayList<>(); + Collections.addAll(newUrls, urls); + return StringUtils.join(newUrls.subList(length, urls.length).toArray(), "/"); + } + + @Override + @Deprecated + public void service(String adptGrpName, String adptName, HttpServletRequest request, HttpServletResponse response) { + + } + + /** + * HTTP 요청에서 클라이언트 IP를 추출합니다. + * X-Forwarded-For 헤더가 있는 경우 이를 우선적으로 사용하고, + * 없는 경우 remoteAddr을 사용합니다. + */ + private String getClientIp(HttpServletRequest request) { + String ipAddress = request.getHeader("X-Forwarded-For"); + if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("WL-Proxy-Client-IP"); + } + if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("HTTP_CLIENT_IP"); + } + if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { + ipAddress = request.getRemoteAddr(); + } + return ipAddress; + } +}