From e177f345f2ef8743b5afb68cd7fe1056195de2ec Mon Sep 17 00:00:00 2001 From: Yunsam Eo Date: Tue, 4 Nov 2025 15:38:12 +0900 Subject: [PATCH 01/17] =?UTF-8?q?.gitmodules=20=EC=9B=90=EB=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitmodules | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.gitmodules b/.gitmodules index 2e4b4a3..02309e3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,15 +1,20 @@ [submodule "elink-online-core"] path = elink-online-core - url = ssh://git@192.168.240.178:18081/eapim/elink-online-core.git + url = ../elink-online-core.git +// url = ssh://git@192.168.240.178:18081/eapim/elink-online-core.git [submodule "elink-online-transformer"] path = elink-online-transformer - url = ssh://git@192.168.240.178:18081/eapim/elink-online-transformer.git + url = ../elink-online-transformer.git +// url = ssh://git@192.168.240.178:18081/eapim/elink-online-transformer.git [submodule "elink-online-common"] path = elink-online-common - url = ssh://git@192.168.240.178:18081/eapim/elink-online-common.git + url = ../eapim/elink-online-common.git +// url = ssh://git@192.168.240.178:18081/eapim/elink-online-common.git [submodule "elink-online-emsclient"] path = elink-online-emsclient - url = ssh://git@192.168.240.178:18081/eapim/elink-online-emsclient.git + url = ../elink-online-emsclient.git +// url = ssh://git@192.168.240.178:18081/eapim/elink-online-emsclient.git [submodule "elink-online-core-jpa"] path = elink-online-core-jpa - url = ssh://git@192.168.240.178:18081/eapim/elink-online-core-jpa.git + url = ../elink-online-core-jpa.git +// url = ssh://git@192.168.240.178:18081/eapim/elink-online-core-jpa.git From 577af1978fe6d3bbb2d91807734c5df80847b6fd Mon Sep 17 00:00:00 2001 From: Yunsam Eo Date: Tue, 4 Nov 2025 16:15:41 +0900 Subject: [PATCH 02/17] =?UTF-8?q?.gitmodules=20=EC=9B=90=EB=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitmodules | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.gitmodules b/.gitmodules index 02309e3..114733c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,20 +1,15 @@ [submodule "elink-online-core"] path = elink-online-core url = ../elink-online-core.git -// url = ssh://git@192.168.240.178:18081/eapim/elink-online-core.git [submodule "elink-online-transformer"] path = elink-online-transformer url = ../elink-online-transformer.git -// url = ssh://git@192.168.240.178:18081/eapim/elink-online-transformer.git [submodule "elink-online-common"] path = elink-online-common url = ../eapim/elink-online-common.git -// url = ssh://git@192.168.240.178:18081/eapim/elink-online-common.git [submodule "elink-online-emsclient"] path = elink-online-emsclient url = ../elink-online-emsclient.git -// url = ssh://git@192.168.240.178:18081/eapim/elink-online-emsclient.git [submodule "elink-online-core-jpa"] path = elink-online-core-jpa url = ../elink-online-core-jpa.git -// url = ssh://git@192.168.240.178:18081/eapim/elink-online-core-jpa.git From 8af9e484781454dcc4c481dabd4cb51949d99c1a Mon Sep 17 00:00:00 2001 From: Yunsam Eo Date: Tue, 4 Nov 2025 16:47:10 +0900 Subject: [PATCH 03/17] =?UTF-8?q?.gitmodules=20=ED=8E=B8=EC=A7=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitmodules | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitmodules b/.gitmodules index 114733c..765ac2a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,15 +1,15 @@ [submodule "elink-online-core"] path = elink-online-core - url = ../elink-online-core.git + url = ssh://git@192.168.240.178:18081/eapim/elink-online-core.git [submodule "elink-online-transformer"] path = elink-online-transformer - url = ../elink-online-transformer.git + url = ssh://git@192.168.240.178:18081/eapim/elink-online-transformer.git [submodule "elink-online-common"] path = elink-online-common - url = ../eapim/elink-online-common.git + url = ssh://git@192.168.240.178:18081/eapim/elink-online-common.git [submodule "elink-online-emsclient"] path = elink-online-emsclient - url = ../elink-online-emsclient.git + url = ssh://git@192.168.240.178:18081/eapim/elink-online-emsclient.git [submodule "elink-online-core-jpa"] path = elink-online-core-jpa - url = ../elink-online-core-jpa.git + url = ssh://git@192.168.240.178:18081/eapim/elink-online-core-jpa.git \ No newline at end of file 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 04/17] =?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 05/17] =?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; + } +} From 733efee74184e419b72cb0760419e4c26e7e14c9 Mon Sep 17 00:00:00 2001 From: 25W0075 <25W0075@P9801Z.kjbank.dom> Date: Mon, 17 Nov 2025 16:56:25 +0900 Subject: [PATCH 06/17] =?UTF-8?q?async=20response=20message=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ApiAdapterController.java | 441 +++--- .../adapter/service/ApiAdapterService.java | 1180 +++++++++++------ 2 files changed, 1051 insertions(+), 570 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 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..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,381 +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.*; - -@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, "")); - - 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 = ""; - } - - 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; - } - - - 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; + } +} From 53084b3bce9cba81f5185a9f7823f5bca1ebe72f Mon Sep 17 00:00:00 2001 From: 25W0075 <25W0075@P9801Z.kjbank.dom> Date: Thu, 20 Nov 2025 09:57:19 +0900 Subject: [PATCH 07/17] =?UTF-8?q?conflict=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ApiAdapterController.java | 253 ------ .../adapter/service/ApiAdapterService.java | 800 ------------------ 2 files changed, 1053 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 37edc79..b4bba6e 100644 --- a/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java +++ b/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java @@ -1,256 +1,3 @@ -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(); - } - - -======= package com.eactive.eai.adapter.controller; import java.util.Date; 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 66460f8..8a87a13 100644 --- a/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java +++ b/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java @@ -1,803 +1,3 @@ -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; - } -} -======= package com.eactive.eai.adapter.service; import com.eactive.eai.adapter.AdapterGroupVO; From 8b0292d90c016ae027341a4de7be087353cec1c3 Mon Sep 17 00:00:00 2001 From: 25W0075 <25W0075@P9801Z.kjbank.dom> Date: Wed, 26 Nov 2025 17:47:05 +0900 Subject: [PATCH 08/17] =?UTF-8?q?find=20adapter=20uri=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ApiAdapterController.java | 570 +++++++++--------- 1 file changed, 285 insertions(+), 285 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 1c66bf1..855cc64 100644 --- a/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java +++ b/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java @@ -1,286 +1,286 @@ -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.stdmessage.STDMessageDAO; -import com.eactive.eai.common.util.ApplicationContextProvider; -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; -import com.eactive.eai.data.entity.onl.stdmessage.StandardMessageInfo; - -@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); - - 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 =""; - if (asyncMsgStyle == null || asyncMsgStyle.trim().isEmpty()) { - responseBody = makeResponseBodyMsg(); - } else { - responseBody = 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) throws Exception { - if (StringUtils.isBlank(apiUri)) { - return null; - } - - //** jwhong TSEAIHS04의 api full path와 비교하여 adapter를 가져온다 - STDMessageDAO dao = ApplicationContextProvider.getContext().getBean(STDMessageDAO.class); - StandardMessageInfo stdInfo = dao.getSTDMsgByPath(apiUri); - String serviceKey = stdInfo.getBzwksvckeyname(); - int idx = serviceKey.indexOf(":"); - String adapterGrpName = (idx != -1) ? serviceKey.substring(0, idx) : serviceKey; // ':' 이전 문자열 추출 - //*** - - for (int i = 0; i < 10; i++) { - HttpDynamicInAdapterUri adptUri = manager.getAdptUri(apiUri); - if (adptUri != null) { - if (adptUri.getAdptGrpName().equals(adapterGrpName)) { - 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() { - - Map dataMap = new HashMap<>(); - dataMap.put("result", 1); - Map map = new HashMap<>(); - - map.put("code", "200"); - map.put("data", dataMap); - map.put("message", "정상 처리 되었습니다."); - - JSONObject json = new JSONObject(); - json.putAll(map); - - return json.toJSONString(); - } - -/* - 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(); - } - */ - - +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.stdmessage.STDMessageDAO; +import com.eactive.eai.common.util.ApplicationContextProvider; +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; +import com.eactive.eai.data.entity.onl.stdmessage.StandardMessageInfo; + +@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); + + 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 =""; + if (asyncMsgStyle == null || asyncMsgStyle.trim().isEmpty()) { + responseBody = makeResponseBodyMsg(); + } else { + responseBody = 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) throws Exception { + if (StringUtils.isBlank(apiUri)) { + return null; + } + + //** jwhong TSEAIHS04의 api full path와 비교하여 adapter를 가져온다 + STDMessageDAO dao = ApplicationContextProvider.getContext().getBean(STDMessageDAO.class); + StandardMessageInfo stdInfo = dao.getSTDMsgByPath(apiUri); + String serviceKey = stdInfo.getBzwksvckeyname(); + int idx = serviceKey.indexOf(":"); + String adapterGrpName = (idx != -1) ? serviceKey.substring(0, idx) : serviceKey; // ':' 이전 문자열 추출 + //*** + + for (int i = 0; i < 10; i++) { + HttpDynamicInAdapterUri adptUri = manager.getAdptUri(apiUri); + if (adptUri != null) { + if (adptUri.getAdptGrpName().equals(adapterGrpName)) { + 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() { + + Map dataMap = new HashMap<>(); + dataMap.put("result", 1); + Map map = new HashMap<>(); + + map.put("code", "200"); + map.put("data", dataMap); + map.put("message", "정상 처리 되었습니다."); + + JSONObject json = new JSONObject(); + json.putAll(map); + + return json.toJSONString(); + } + +/* + 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 12e833c9a49e0e93c16cb5328b93e389c5fa6ab8 Mon Sep 17 00:00:00 2001 From: 25W0075 <25W0075@P9801Z.kjbank.dom> Date: Wed, 26 Nov 2025 17:58:11 +0900 Subject: [PATCH 09/17] =?UTF-8?q?debug=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eactive/eai/adapter/controller/ApiAdapterController.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 855cc64..66794c6 100644 --- a/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java +++ b/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java @@ -186,13 +186,16 @@ public class ApiAdapterController implements HttpAdapterServiceKey { for (int i = 0; i < 10; i++) { HttpDynamicInAdapterUri adptUri = manager.getAdptUri(apiUri); if (adptUri != null) { - if (adptUri.getAdptGrpName().equals(adapterGrpName)) { + System.out.println("*****adptUri.getAdptGrpName() "+ adptUri.getAdptGrpName()); + System.out.println("*****getAdptGrpName "+ getAdptGrpName); + if (adptUri.getAdptGrpName().equals(getAdptGrpName)) { return adptUri; } } // /api/v1/public apiUri = StringUtils.substringBeforeLast(apiUri, "/"); + System.out.println("*****apiUri "+ apiUri); if (apiUri.length() < 4) { // /api return null; } From 3e45cbc8d70cea607ff3e5b00a1dc1c490461c3c Mon Sep 17 00:00:00 2001 From: 25W0075 <25W0075@P9801Z.kjbank.dom> Date: Wed, 26 Nov 2025 18:02:06 +0900 Subject: [PATCH 10/17] =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eactive/eai/adapter/controller/ApiAdapterController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 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 66794c6..8600aeb 100644 --- a/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java +++ b/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java @@ -187,8 +187,8 @@ public class ApiAdapterController implements HttpAdapterServiceKey { HttpDynamicInAdapterUri adptUri = manager.getAdptUri(apiUri); if (adptUri != null) { System.out.println("*****adptUri.getAdptGrpName() "+ adptUri.getAdptGrpName()); - System.out.println("*****getAdptGrpName "+ getAdptGrpName); - if (adptUri.getAdptGrpName().equals(getAdptGrpName)) { + System.out.println("*****getAdptGrpName "+ adapterGrpName); + if (adptUri.getAdptGrpName().equals(adapterGrpName)) { return adptUri; } } From 687895ffc0c75e7720e1918b0c9dfaea0995a74d Mon Sep 17 00:00:00 2001 From: 25W0075 <25W0075@P9801Z.kjbank.dom> Date: Thu, 27 Nov 2025 18:35:21 +0900 Subject: [PATCH 11/17] =?UTF-8?q?timestamp=EB=A5=BC=20=EC=B4=88=EB=8B=A8?= =?UTF-8?q?=EC=9C=84=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eactive/eai/adapter/controller/ApiAdapterController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 8600aeb..e62e722 100644 --- a/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java +++ b/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java @@ -69,7 +69,7 @@ public class ApiAdapterController implements HttpAdapterServiceKey { HttpDynamicInAdapterUri adptUri = findAdptUri(apiUri, HttpDynamicInAdapterManager.getInstance()); //Received time , jwhong - long receivedTimeMillis = System.currentTimeMillis(); + long receivedTimeMillis = System.currentTimeMillis() / 1000; String receivedTimeStr = String.valueOf(receivedTimeMillis); if (logger.isDebug()) { From 22b0f0b5f165333812babc01b4ffd99f0c5db49b Mon Sep 17 00:00:00 2001 From: 25W0075 <25W0075@P9801Z.kjbank.dom> Date: Thu, 27 Nov 2025 18:50:16 +0900 Subject: [PATCH 12/17] timeStamp --- .../com/eactive/eai/adapter/controller/ApiAdapterController.java | 1 + 1 file changed, 1 insertion(+) 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 e62e722..86c993b 100644 --- a/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java +++ b/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java @@ -71,6 +71,7 @@ public class ApiAdapterController implements HttpAdapterServiceKey { //Received time , jwhong long receivedTimeMillis = System.currentTimeMillis() / 1000; String receivedTimeStr = String.valueOf(receivedTimeMillis); + System.out.println("*** inbound receivedTimeStr ***"+receivedTimeStr); if (logger.isDebug()) { logger.debug("ApiAdapterController] service request uri : " + servletRequest.getRequestURI()); From 3a2dbb055d2d0b957f9054ecea89523a1665cb1c Mon Sep 17 00:00:00 2001 From: 25W0075 <25W0075@P9801Z.kjbank.dom> Date: Thu, 27 Nov 2025 19:10:59 +0900 Subject: [PATCH 13/17] =?UTF-8?q?=EB=8B=A4=EC=8B=9C=20=EB=B0=80=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../eactive/eai/adapter/controller/ApiAdapterController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 86c993b..de37328 100644 --- a/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java +++ b/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java @@ -69,7 +69,7 @@ public class ApiAdapterController implements HttpAdapterServiceKey { HttpDynamicInAdapterUri adptUri = findAdptUri(apiUri, HttpDynamicInAdapterManager.getInstance()); //Received time , jwhong - long receivedTimeMillis = System.currentTimeMillis() / 1000; + long receivedTimeMillis = System.currentTimeMillis(); String receivedTimeStr = String.valueOf(receivedTimeMillis); System.out.println("*** inbound receivedTimeStr ***"+receivedTimeStr); From 616156afb8a1126ec361eb91e64dcdad60c1ac0f Mon Sep 17 00:00:00 2001 From: 25W0075 <25W0075@P9801Z.kjbank.dom> Date: Fri, 28 Nov 2025 09:49:07 +0900 Subject: [PATCH 14/17] =?UTF-8?q?=EC=9D=BC=EB=8B=A8=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9C=84=ED=95=B4=20=EB=AC=B4=EC=A1=B0=EA=B1=B4=20?= =?UTF-8?q?2=20return?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/eactive/eai/custom/message/InterfaceMapperKBANK.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/eactive/eai/custom/message/InterfaceMapperKBANK.java b/src/main/java/com/eactive/eai/custom/message/InterfaceMapperKBANK.java index 6980326..39c2972 100644 --- a/src/main/java/com/eactive/eai/custom/message/InterfaceMapperKBANK.java +++ b/src/main/java/com/eactive/eai/custom/message/InterfaceMapperKBANK.java @@ -19,7 +19,7 @@ public class InterfaceMapperKBANK extends DefaultInterfaceMapper { @Override public String getInExDivision(StandardMessage standardMessage) { - return "1"; + return "2"; } @Override From 99eb22137792497ef5e5d72b55310ebad628ac96 Mon Sep 17 00:00:00 2001 From: 25W0075 <25W0075@P9801Z.kjbank.dom> Date: Tue, 2 Dec 2025 15:42:25 +0900 Subject: [PATCH 15/17] system print for test --- .../eai/adapter/controller/ApiAdapterController.java | 9 +++++++++ 1 file changed, 9 insertions(+) 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 de37328..4da2796 100644 --- a/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java +++ b/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java @@ -184,6 +184,15 @@ public class ApiAdapterController implements HttpAdapterServiceKey { String adapterGrpName = (idx != -1) ? serviceKey.substring(0, idx) : serviceKey; // ':' 이전 문자열 추출 //*** + System.out.println("====== adptUriMap 상세 내용 ======="); + for (Map.Entry entry : manager.adptUriMap.entrySet()) { + HttpDynamicInAdapterUri uriObj = entry.getValue(); + System.out.println("GroupName="+uriObj.getAdptGrpName() + + ", AdapterName=" + uirObj.getAdptName() + + ", URI=" + uriObj.getUri()); + } + System.out.println("================================"); + for (int i = 0; i < 10; i++) { HttpDynamicInAdapterUri adptUri = manager.getAdptUri(apiUri); if (adptUri != null) { From c5fef773fd35900ad7f7bab9e8b185674172d479 Mon Sep 17 00:00:00 2001 From: 25W0075 <25W0075@P9801Z.kjbank.dom> Date: Tue, 2 Dec 2025 15:49:50 +0900 Subject: [PATCH 16/17] test --- .../eactive/eai/adapter/controller/ApiAdapterController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 4da2796..bcd54a9 100644 --- a/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java +++ b/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java @@ -188,7 +188,7 @@ public class ApiAdapterController implements HttpAdapterServiceKey { for (Map.Entry entry : manager.adptUriMap.entrySet()) { HttpDynamicInAdapterUri uriObj = entry.getValue(); System.out.println("GroupName="+uriObj.getAdptGrpName() - + ", AdapterName=" + uirObj.getAdptName() + + ", AdapterName=" + uriObj.getAdptName() + ", URI=" + uriObj.getUri()); } System.out.println("================================"); From d1cc7c67403119665933b8a1a3be8d334416b75a Mon Sep 17 00:00:00 2001 From: Rinjae Date: Thu, 4 Dec 2025 14:04:08 +0900 Subject: [PATCH 17/17] =?UTF-8?q?weblogic-web.xml=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- WebContent/WEB-INF/weblogic-web.xml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/WebContent/WEB-INF/weblogic-web.xml b/WebContent/WEB-INF/weblogic-web.xml index 3d4f45b..2e359f1 100644 --- a/WebContent/WEB-INF/weblogic-web.xml +++ b/WebContent/WEB-INF/weblogic-web.xml @@ -34,7 +34,7 @@ contextConfigLocation /WEB-INF/applicationContext.xml - + default @@ -70,17 +70,17 @@ - - - RestApiDynamicInAdapter - com.eactive.eai.adapter.http.dynamic.RestApiAdapterMain - 2 - - - RestApiDynamicInAdapter - /API/* - /api/* - + + + + + + + + + + +