diff --git a/WebContent/WEB-INF/properties/env.D.properties b/WebContent/WEB-INF/properties/env.D.properties index f73d61a..0bd3db5 100644 --- a/WebContent/WEB-INF/properties/env.D.properties +++ b/WebContent/WEB-INF/properties/env.D.properties @@ -20,4 +20,3 @@ eai.systemmode=D eai.systemtype=API eai.tableowner=AGWADM eai.server.extractor=[0,2],[0,2],[-2] - 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 6d8d7db..11feef8 100644 --- a/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java +++ b/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java @@ -11,6 +11,7 @@ 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.util.AntPathMatcher; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -27,8 +28,8 @@ 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.stdmessage.STDMessageManager; +import com.eactive.eai.common.stdmessage.STDMsgInfoAddOnVO; import com.eactive.eai.common.util.DatetimeUtil; import com.eactive.eai.common.util.InboundErrorLogger; import com.eactive.eai.common.util.Logger; @@ -40,7 +41,6 @@ import com.eactive.eai.inbound.error.InboundErrorInfoVO; import org.json.simple.JSONObject; import java.util.HashMap; import java.util.Map; -import com.eactive.eai.data.entity.onl.stdmessage.StandardMessageInfo; @RestController public class ApiAdapterController implements HttpAdapterServiceKey { @@ -65,16 +65,24 @@ public class ApiAdapterController implements HttpAdapterServiceKey { //** jwhong TSEAIHS04의 api full path와 비교하여 adapter를 가져온다 String methodAndUri = servletRequest.getMethod() + "|" + apiUri; HttpDynamicInAdapterUri adptUri = null; - String adapterGrpName =""; - String apiSvcCode = ""; + String bzwkSvcKeyName = ""; // Adapter Group별 Action Class에 따라 구성이 달라짐. 예) _AGW_IN_RST_SyS:POST/account/{acc_no} + String adapterGrpName = ""; // Adapter Group명 예) _AGW_IN_RST_SyS : API_PATH(/api/test) + String apiSvcCode = ""; // eaiSvcCd 예) LONNCHCON00005S2 + String apiFullPathKey = ""; // 예) POST|/api/test/account/list, POST|/api/test/account/{acc_no} + Map pathVariables = null; try { - STDMessageDAO dao = ApplicationContextProvider.getContext().getBean(STDMessageDAO.class); - StandardMessageInfo stdInfo = dao.getSTDMsgByPath(methodAndUri); - String serviceKey = stdInfo.getBzwksvckeyname(); - int idx = serviceKey.indexOf(":"); - adapterGrpName = (idx != -1) ? serviceKey.substring(0, idx) : serviceKey; // ':' 이전 문자열 추출 - apiSvcCode = stdInfo.getEaisvcname(); - //아래 원래 Logic + // PathVariable(ex:/api/test/account/{acc_no}) 대응 및 DAO조회 제거. + // /api/test/account/1234567 호출시 /api/test/account/{acc_no} API 로 식별. + STDMessageManager manager = STDMessageManager.getInstance(); + STDMsgInfoAddOnVO stdMsgInfo = manager.getStdMsgInfoAddOn(methodAndUri); + bzwkSvcKeyName = stdMsgInfo.getBzwksvckeyname(); + apiSvcCode = stdMsgInfo.getEaiSvcCd(); + adapterGrpName = stdMsgInfo.gAdapterGroupName(); + apiFullPathKey = stdMsgInfo.getApiFullPath(); + if (STDMessageManager.isPathVariable(apiFullPathKey)) { + pathVariables = new AntPathMatcher().extractUriTemplateVariables(apiFullPathKey, methodAndUri); + } + adptUri = findAdptUri(apiUri, HttpDynamicInAdapterManager.getInstance(), adapterGrpName); } catch (Exception e) { adptUri = null; @@ -121,6 +129,9 @@ public class ApiAdapterController implements HttpAdapterServiceKey { // jwhong, put api received time, eaiSvcCode transactionProp.put(INBOUND_REQUESTED_TIME, receivedTimeStr); transactionProp.put(API_SERVICE_CODE, apiSvcCode); + if (pathVariables != null) { + transactionProp.put(INBOUND_PATH_VARIABLES, pathVariables); + } try { String responseData = service.callApi(servletRequest, servletResponse, httpProp, adapterGroupVO, adapterVO, transactionProp); @@ -206,7 +217,6 @@ public class ApiAdapterController implements HttpAdapterServiceKey { // - for (int i = 0; i < 10; i++) { HttpDynamicInAdapterUri adptUri = manager.getAdptUri(apiUri); if (adptUri != null) { 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 b4a9318..1f7be85 100644 --- a/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java +++ b/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java @@ -146,6 +146,8 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { case PUT: if (StringUtils.contains(request.getContentType(), "application/x-www-form-urlencoded")) { isParameterType = true; + } else if (request.getContentType() == null || request.getContentType().isEmpty()) { // jwhong + isParameterType = true; } else { isParameterType = false; } @@ -344,7 +346,7 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { // jwhong decrypt - private String doPreDecryption(String eaiBody, Properties transactionProp, HttpServletRequest request) { + 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); @@ -379,6 +381,11 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { byte[] decryptedMessage = null; decryptedMessage = doInboundPreDecrypt(eaiBody, decryptAlgorithm,clientSecret,secretAES256Iv, secretAES256Key ); + if (decryptedMessage == null) { + throw new Exception("[HttpClient5AdapterServiceRest] Decrypt Error : Invalid encrypted message"); + } + + String resultMessage = new String(decryptedMessage, StandardCharsets.UTF_8 ); return resultMessage; //return new String(decryptedMessage, StandardCharsets.UTF_8 ); @@ -451,25 +458,28 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { } - private byte[] doInboundPreDecrypt(String eaiStringBody, String decryptAlgorithm, String clientSecretKey, String secretAES256Iv, String secretAES256Key) { + 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("[HttpClient5AdapterServiceRest] Cannot decrypt Error : input is plain text"); + } + //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)); + 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); - System.out.println("디코딩 성공, 길이: " + decoded.length); + logger.debug("디코딩 성공, 길이: " + decoded.length); } catch (IllegalArgumentException e) { - System.out.println("Base64 디코딩 실패: " + e.getMessage()); + logger.debug("Base64 디코딩 실패: " + e.getMessage()); } // end test source @@ -485,7 +495,7 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { e.printStackTrace(); logger.error("HttpClientAdapterServiceRest] AES128 Decryption error=" + e.getMessage()); } - break; + break; case "AES128-TOGETHER": try { String key128 = clientSecretKey.substring(44,60); //togetherEncoder 경우는 substring(44,60) 이네?? @@ -584,12 +594,12 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { try { JSONParser parser = new JSONParser(); JSONObject jsonObject = (JSONObject) parser.parse(eaiStringBody); - decryptedBodyMessage = (String) jsonObject.get(decryptedJsonKey); + decryptedBodyMessage = (String) jsonObject.get(decryptedJsonKey); } catch (Exception e) { e.printStackTrace(); logger.error("HttpClient5AdapterServiceRest] extractBodyMsg error : " + e.getMessage()); } - + return decryptedBodyMessage; } @@ -600,17 +610,16 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { //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)); + 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); - System.out.println("디코딩 성공, 길이: " + decoded.length); + logger.debug("디코딩 성공, 길이: " + decoded.length); } catch (IllegalArgumentException e) { - System.out.println("Base64 디코딩 실패: " + e.getMessage()); + logger.debug("Base64 디코딩 실패: " + e.getMessage()); } // end test source @@ -703,7 +712,7 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { logger.error(e.getMessage()); } - System.out.println("Token is: " + Token); + logger.debug("Token is: " + Token); return Token; } @@ -719,7 +728,7 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { tokenClientId = ""; } - System.out.println("Token Client ID: " + tokenClientId); + logger.debug("Token Client ID: " + tokenClientId); return tokenClientId; } diff --git a/src/main/java/com/eactive/eai/authserver/custom/KjbMGOAuth2Controller.java b/src/main/java/com/eactive/eai/authserver/custom/KjbMGOAuth2Controller.java index 00781b8..b151ac3 100644 --- a/src/main/java/com/eactive/eai/authserver/custom/KjbMGOAuth2Controller.java +++ b/src/main/java/com/eactive/eai/authserver/custom/KjbMGOAuth2Controller.java @@ -92,7 +92,7 @@ public class KjbMGOAuth2Controller { } ClientDetails clientDetails = OAuth2Manager.getInstance().getClientDeatilsStore().get(clientId); - verifyClient(clientDetails, clientId, scopeSet); + verifyClient(clientDetails, clientId, clientSecret, scopeSet); String traceId = UUID.randomUUID().toString().replace("-", ""); response.setHeader(HEADER_TRACEID, traceId); @@ -139,7 +139,7 @@ public class KjbMGOAuth2Controller { } } - private void verifyClient(ClientDetails clientDetails, String clientId, Set scopeSet) + private void verifyClient(ClientDetails clientDetails, String clientId, String clientSecret, Set scopeSet) throws JwtAuthException { if (StringUtils.isBlank(clientId)) { @@ -148,13 +148,24 @@ public class KjbMGOAuth2Controller { "Invalid Mandatory Field {client_id}"); } - if (clientDetails == null) { throw new JwtAuthException( String.format("%d%s%s", HttpStatus.UNAUTHORIZED.value(), SERVICE_CODE_ACCESS_TOKEN, "00"), "Unauthorized. [client not found]"); } + if (StringUtils.isBlank(clientSecret)) { + throw new JwtAuthException( + String.format("%d%s%s", HttpStatus.BAD_REQUEST.value(), SERVICE_CODE_ACCESS_TOKEN, "02"), + "Invalid Mandatory Field {client_secret}"); + } + + if (!StringUtils.equals(clientDetails.getClientSecret(), clientSecret)) { + throw new JwtAuthException( + String.format("%d%s%s", HttpStatus.UNAUTHORIZED.value(), SERVICE_CODE_ACCESS_TOKEN, "00"), + "Unauthorized. [Bad client credentials(Client Secret is not match)]"); + } + if (scopeSet.isEmpty()) { throw new JwtAuthException( String.format("%d%s%s", HttpStatus.BAD_REQUEST.value(), SERVICE_CODE_ACCESS_TOKEN, "02"), diff --git a/src/main/java/com/eactive/eai/custom/kjb/adapter/http/client/filter/AsyncReponseFilter.java b/src/main/java/com/eactive/eai/custom/kjb/adapter/http/client/filter/AsyncReponseFilter.java index a381f31..01eeb53 100644 --- a/src/main/java/com/eactive/eai/custom/kjb/adapter/http/client/filter/AsyncReponseFilter.java +++ b/src/main/java/com/eactive/eai/custom/kjb/adapter/http/client/filter/AsyncReponseFilter.java @@ -6,8 +6,6 @@ import java.util.TreeMap; import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceKey; import com.eactive.eai.common.TransactionContextKeys; -import com.eactive.eai.common.property.PropGroupVO; -import com.eactive.eai.common.property.PropManager; import com.eactive.eai.common.util.Logger; @@ -22,7 +20,6 @@ public class AsyncReponseFilter implements HttpClientAdapterFilter, HttpAdapterS throws Exception { logger.debug("AsyncReponseFilter] PreFilter Processing Start!!"); - Object returnMessage = message; String traceId = tempProp.getProperty(TransactionContextKeys.TRANSACTION_UUID, ""); Properties filterHeaders = (Properties) tempProp.get("FILTERHEADER"); @@ -31,13 +28,7 @@ public class AsyncReponseFilter implements HttpClientAdapterFilter, HttpAdapterS tempProp.put("FILTERHEADER", filterHeaders); } try { - Properties inboundHeader = (Properties)tempProp.get(INBOUND_HEADER); - Map inboundHeaderMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - - // Properties 내용을 모두 복사 - for (String name : inboundHeader.stringPropertyNames()) { - inboundHeaderMap.put(name, inboundHeader.getProperty(name)); - } + Map inboundHeaderMap = getInboundHeaderProp(tempProp); if (!inboundHeaderMap.isEmpty()) { if (inboundHeaderMap.containsKey(X_TRACE_ID)) { @@ -52,7 +43,35 @@ public class AsyncReponseFilter implements HttpClientAdapterFilter, HttpAdapterS logger.error(e.getMessage()); } - return returnMessage; + return message; + } + + public Map getInboundHeaderProp(Properties prop) { + Properties header = new Properties(); + Map inboundHeaderMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + try { + Object headerObj = prop.get(HttpAdapterServiceKey.INBOUND_HEADER); + if (headerObj instanceof Properties) { //tomcat + header = (Properties) headerObj; + for (String name : header.stringPropertyNames()) { + inboundHeaderMap.put(name, header.getProperty(name)); + } + } else if (headerObj instanceof String) { //weblogic + String str = (String) headerObj; + str = str.substring(1, str.length() - 1); + // key=value 쌍 분리 + String[] entries = str.split(","); + for (String entry : entries) { + String[] kv = entry.split("=", 2); + if (kv.length == 2) { + inboundHeaderMap.put(kv[0].trim(), kv[1].trim()); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return inboundHeaderMap; } @Override