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; import com.eactive.eai.common.context.ElinkTransactionContext; @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 private boolean encryptResponseApply; // inbound에 대한 응답 암호화 여부 flag 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)); transactionProp.put(INBOUND_EXTPARAMS, StringUtils.defaultString(request.getQueryString())); 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("BLOCK_IP", httpProp.getProperty("BLOCK_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 String inboundToken = getHeaders(request).getOrDefault(INBOUND_TOKEN, "").toString(); if (StringUtils.isNotBlank(inboundToken) && StringUtils.startsWith(inboundToken, "Bearer ")) { inboundToken = inboundToken.substring(7); } transactionProp.put(INBOUND_TOKEN, inboundToken); transactionProp.put(ENCRYPT_AES256_IV, httpProp.getProperty(ENCRYPT_AES256_IV, "")); //jwhong transactionProp.put(ENCRYPT_AES256_KEY, httpProp.getProperty(ENCRYPT_AES256_KEY, "")); //jwhong // SEED 컬럼암호하 시 Key로 사용함 String seedkey = getHeaders(request).getOrDefault("x-obp-partnercode", "").toString(); ElinkTransactionContext.setSeedKey(seedkey); 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 if ( StringUtils.isNoneBlank(request.getQueryString()) ) { // jwhong isParameterType = true; } else { isParameterType = false; } break; default: break; } if (isParameterType) { paramValue = request.getQueryString(); transactionProp.put(INBOUND_QUERY_STRING, StringUtils.defaultString(paramValue)); // Filter에서 QueryString 검증을 위해 저장 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 { if (request.getContentLength() > 0) { 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 = ""; } // 순수한 Body값을 저장을 위해 위치 변경. transactionProp.put(INBOUND_REQUEST_MESSAGE, paramValue); // paramValue가 null이 아닌 빈문자열(""," ")인 경우에 대비하여 조건 수정. if (StringUtils.isNotBlank(paramValue)) { // 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 = ""; } // 위치변경 : 가공되지 않은 Body값을 저장하기 위하여 위쪽으로 이동. // 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응답) 에 대하여 암호화 하지 않는다. 무조건 안한다. 따라서 아래부분은 구현은 했지만 사용하지 않는다. // 위 2가지 경우 암호화 하는걸로 요청 변경되어 아래 암호화 수행하도록 수정함 encryptResponseApply = StringUtils.equalsIgnoreCase(httpProp.getProperty("ENCRYPT_RESPONSE_APPLY", "N"), "Y"); if ( encryptResponseApply) { result = doPostEncryption(result, transactionProp, request); // jwhong Encrypt } return result; } // jwhong decrypt private String doPreDecryption(String eaiBody, Properties transactionProp, HttpServletRequest request) throws Exception { 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 ); if (decryptedMessage == null) { throw new Exception("[ApiAdapterService] Decrypt Error : Invalid encrypted message"); } String resultMessage = new String(decryptedMessage, StandardCharsets.UTF_8 ); return resultMessage; //return new String(decryptedMessage, StandardCharsets.UTF_8 ); } // jwhong encrypt public String doPostEncryption(String eaiBody, Properties transactionProp, HttpServletRequest request) throws Exception { 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 = ""; 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 ) { clientSecret = clientDetail.getClientSecret(); } } String encryptedMessage = null; encryptedMessage = doInboundPostEncrypt(eaiBody, decryptAlgorithm,clientSecret,secretAES256Iv, secretAES256Key ); if (encryptedMessage == null) { throw new Exception("[ApiAdapterService] Encrypt Error : Invalid PlainText message"); } return encryptedMessage; //String resultMessage = new String(encryptedMessage, StandardCharsets.UTF_8 ); //return resultMessage; } 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) throws Exception { byte[] decryptedMessage = null; //String eaiStringBody = new String(eaiBody, StandardCharsets.UTF_8); eaiStringBody = extractBodyMsg(decryptAlgorithm, eaiStringBody); if (eaiStringBody == null) { throw new Exception("[ApiAdapterService] Cannot decrypt Error : input is plain text"); } //test source logger.debug("Base64 문자열: " + eaiStringBody); logger.debug("Base64 문자열 길이: " + eaiStringBody.length()); logger.debug("Base64 문자열 끝: " + eaiStringBody.substring(eaiStringBody.length() - 10)); // Base64 디코딩 테스트 try { byte[] decoded = Base64.getDecoder().decode(eaiStringBody); logger.debug("디코딩 성공, 길이: " + decoded.length); } catch (IllegalArgumentException e) { logger.debug("Base64 디코딩 실패: " + e.getMessage()); } // end test source switch (decryptAlgorithm) { case "AES128": 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 = ""; decryptedJsonKey = getJsonKey(decryptAlgorithm); 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 String getJsonKey(String Algorithm) { String jsonKey = ""; switch (Algorithm) { case "AES128": case "AES128-TOSS": jsonKey = "preScreeningRequest"; break; case "AES128-TOGETHER": jsonKey = "obpTxData"; break; case "AES256": jsonKey = "preScreeningRequest"; break; case "AES256-KAKAO": jsonKey = "encrypted_data"; break; case "AES256-TOSS": jsonKey = "encryptedData"; break; case "AES256-NICEON": jsonKey = "enc_data"; break; case "AES256GCM": break; default: break; } return jsonKey; } private String doInboundPostEncrypt(String eaiStringBody, String encryptAlgorithm, String clientSecretKey, String secretAES256Iv, String secretAES256Key) { //byte[] encryptedMessage = null; String encryptedStrMessage = null; String encryptedJsonKey = ""; encryptedJsonKey = getJsonKey(encryptAlgorithm); switch (encryptAlgorithm) { case "AES128": case "AES128-TOSS": try { String key128 = clientSecretKey.substring(22,38); //togetherEncoder 경우는 substring(44,60) 이네?? encryptedStrMessage = AESCipher.encrypt(eaiStringBody, key128); //encryptedMessage = encryptedStrMessage.getBytes(StandardCharsets.UTF_8); } catch (Exception e) { e.printStackTrace(); logger.error("HttpClientAdapterServiceRest] AES128 Encryption error=" + e.getMessage()); } break; case "AES128-TOGETHER": try { String key128 = clientSecretKey.substring(44,60); //togetherEncoder 경우는 substring(44,60) 이네?? encryptedStrMessage = AESCipher.encrypt(eaiStringBody, key128); //encryptedMessage = encryptedStrMessage.getBytes(StandardCharsets.UTF_8); } catch (Exception e) { e.printStackTrace(); logger.error("HttpClientAdapterServiceRest] AES128 Encryption error=" + e.getMessage()); } break; case "AES256": try { String key = clientSecretKey.substring(10,42); encryptedStrMessage = AES256Cipher.encrypt(eaiStringBody, key); //encryptedMessage = encryptedStrMessage.getBytes(StandardCharsets.UTF_8); } catch (Exception e) { e.printStackTrace(); logger.error("HttpClientAdapterServiceRest] AES256 Encryption error=" + e.getMessage()); } break; case "AES256-KAKAO": try { encryptedStrMessage = AES256Cipher.encrypt(eaiStringBody, secretAES256Iv, secretAES256Key); //encryptedMessage = encryptedStrMessage.getBytes(StandardCharsets.UTF_8); } catch (Exception e) { e.printStackTrace(); logger.error("HttpClientAdapterServiceRest] AES256 Encryption error=" + e.getMessage()); } break; case "AES256-TOSS": try { encryptedStrMessage = AES256Cipher.encrypt(eaiStringBody, secretAES256Iv, secretAES256Key); //encryptedMessage = encryptedStrMessage.getBytes(StandardCharsets.UTF_8); } catch (Exception e) { e.printStackTrace(); logger.error("HttpClientAdapterServiceRest] AES256 Encryption error=" + e.getMessage()); } break; case "AES256GCM": try { byte[] key = AES256GCMCipher.generateKey(); AES256GCMCipher cipher = new AES256GCMCipher(key); byte[] aad = "metadata".getBytes(); encryptedStrMessage = cipher.encrypt(eaiStringBody , aad); //encryptedMessage = encryptedStrMessage.getBytes(StandardCharsets.UTF_8); } catch (Exception e) { e.printStackTrace(); logger.error("HttpClientAdapterServiceRest] AES256GCM Encryption error=" + e.getMessage()); } break; default: try { encryptedStrMessage = eaiStringBody; //encryptedMessage = eaiStringBody.getBytes(); } catch (Exception e) { e.printStackTrace(); logger.error("HttpClientAdapterServiceRest] doOutboundPostFilter Array copy error=" + e.getMessage()); } break; } Map map = new HashMap<>(); map.put(encryptedJsonKey, encryptedStrMessage); JSONObject json = new JSONObject(); json.putAll(map); return json.toJSONString(); //return encryptedMessage; } private String JwtTokenExtractor(HttpServletRequest request) { String Token = ""; try { Token = JwtAuthFilter.extractJWTToken(request); } catch (Exception e) { logger.error(e.getMessage()); } logger.debug("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 = ""; } logger.debug("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; } }