From 12d8f157cc101147e1d4043ae1711970ba4ce6e0 Mon Sep 17 00:00:00 2001 From: jaewohong Date: Fri, 5 Dec 2025 15:37:49 +0900 Subject: [PATCH] =?UTF-8?q?=EC=9B=90=EA=B2=A9=20=EB=B8=8C=EB=9E=9C?= =?UTF-8?q?=EC=B9=98=EC=97=90=EC=84=9C=20online-eapim=20=EA=B4=80=EB=A0=A8?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=20=EA=B0=80=EC=A0=B8=EC=98=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../agent/host/adapter_socket2_agent1.jsp | 114 +++++ .../agent/host/adapter_socket2_agent2.jsp | 81 +++ .../agent/host/adapter_socket2_startstop.jsp | 54 ++ .../controller/ApiAdapterController.java | 2 - .../adapter/service/ApiAdapterService.java | 22 +- .../config/AuthorizationServerConfig.java | 2 +- .../config/OAuthRequestLoggingFilter.java | 6 +- .../authserver/config/RequestContextData.java | 3 +- .../custom/BearerTokenContoller.java | 125 +++++ .../authserver/custom/BearerTokenFilter.java | 85 ++++ .../authserver/custom/BearerTokenInfo.java | 49 ++ .../authserver/custom/BearerTokenService.java | 97 ++++ .../custom/KjbMGOAuth2AccessTokenRequest.java | 63 +++ .../KjbMGOAuth2AccessTokenResponse.java | 105 ++++ .../custom/KjbMGOAuth2Controller.java | 288 +++++++++++ .../eai/authserver/custom/SecurityConfig.java | 58 +++ .../adapter/app/impl/JwtTokenCreator.java | 477 ++++++++++++++++++ .../eai/custom/message/GUIDGeneratorKJB.java | 83 +++ .../custom/message/InterfaceMapperKBANK.java | 2 +- .../custom/message/InterfaceMapperKJB.java | 202 ++++++++ 20 files changed, 1910 insertions(+), 8 deletions(-) create mode 100644 WebContent/agent/host/adapter_socket2_agent1.jsp create mode 100644 WebContent/agent/host/adapter_socket2_agent2.jsp create mode 100644 WebContent/agent/host/adapter_socket2_startstop.jsp create mode 100644 src/main/java/com/eactive/eai/authserver/custom/BearerTokenContoller.java create mode 100644 src/main/java/com/eactive/eai/authserver/custom/BearerTokenFilter.java create mode 100644 src/main/java/com/eactive/eai/authserver/custom/BearerTokenInfo.java create mode 100644 src/main/java/com/eactive/eai/authserver/custom/BearerTokenService.java create mode 100644 src/main/java/com/eactive/eai/authserver/custom/KjbMGOAuth2AccessTokenRequest.java create mode 100644 src/main/java/com/eactive/eai/authserver/custom/KjbMGOAuth2AccessTokenResponse.java create mode 100644 src/main/java/com/eactive/eai/authserver/custom/KjbMGOAuth2Controller.java create mode 100644 src/main/java/com/eactive/eai/authserver/custom/SecurityConfig.java create mode 100644 src/main/java/com/eactive/eai/custom/adapter/app/impl/JwtTokenCreator.java create mode 100644 src/main/java/com/eactive/eai/custom/message/GUIDGeneratorKJB.java create mode 100644 src/main/java/com/eactive/eai/custom/message/InterfaceMapperKJB.java diff --git a/WebContent/agent/host/adapter_socket2_agent1.jsp b/WebContent/agent/host/adapter_socket2_agent1.jsp new file mode 100644 index 0000000..6eac161 --- /dev/null +++ b/WebContent/agent/host/adapter_socket2_agent1.jsp @@ -0,0 +1,114 @@ + +<%@ page contentType="text/xml; charset=utf-8"%> +<%@ page import="com.eactive.eai.adapter.socket2.config.MonitoringUtil"%> +<%@ page import="java.util.*,com.eactive.eai.common.util.Logger" %> + + + + + + + + + + + + + + + + + + +<%! + static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT); +%> + +<% + // + // Socket2 status info + + + String eaiSvrInstNm = request.getParameter("eaiSvrInstNm"); + String adapterGroupName = request.getParameter("adapterGroupName"); + + if (eaiSvrInstNm == null) + eaiSvrInstNm = ""; + + if (adapterGroupName == null) + adapterGroupName = ""; + + String stateColor = ""; + String stateText = ""; + + String startColor = ""; + String startText = ""; + String startStop = ""; + + + String[][] arrList = null ; + try { + if(adapterGroupName.length() > 0) { + arrList = MonitoringUtil.adapterStatus(adapterGroupName); + } + else { + arrList = MonitoringUtil.adapterList1(); + } + } catch ( Exception e ) { + if (logger.isError()){ + logger.error(e.toString()); + } + } + + // ϵ arrList null ƴϸ鼭 迭̰ 0 Exception ߻ + // ʵ ϱ . (2008-06-30) + if( arrList == null || arrList.length == 0 ) { +%> + + <%=eaiSvrInstNm%> + + + + + + + + + + + + + +<% + + } else { + int col = arrList[0].length ; + int row = arrList.length ; + + for( int i = 0 ; i < row ; i++ ) { + out.println(""); + out.println("" + eaiSvrInstNm + ""); + for( int j = 0 ; j < col ; j++ ) { + if(j == 2) { + out.println(""); + } else { + out.println("" + arrList[i][j] + ""); + } + } + + // ׼ + if(arrList[i] != null && arrList[i].length > 4 ) { + if( "STARTED".equals(arrList[i][7]) || "STARTING".equals(arrList[i][7])) { + startStop = "03" ; // stop + } else { + startStop = "01" ; // start + } + } + + out.println(""+ startStop +""); + out.println(""); + } + } +%> + + diff --git a/WebContent/agent/host/adapter_socket2_agent2.jsp b/WebContent/agent/host/adapter_socket2_agent2.jsp new file mode 100644 index 0000000..6daf110 --- /dev/null +++ b/WebContent/agent/host/adapter_socket2_agent2.jsp @@ -0,0 +1,81 @@ + +<%@ page contentType="text/xml; charset=utf-8"%> +<%@ page import="com.eactive.eai.adapter.socket2.config.MonitoringUtil"%> +<%@ page import="java.util.*,com.eactive.eai.common.util.Logger" %> + + + + + + + + + + + + + + + + +<%! + static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT); +%> +<% + // + // Socket2 connection info + + String eaiSvrInstNm = request.getParameter("eaiSvrInstNm"); + + if (eaiSvrInstNm == null) + eaiSvrInstNm = ""; + + String stateColor = ""; + String stateText = ""; + + String startColor = ""; + String startText = ""; + String startStop = ""; + + String[][] arrList = null ; + try { + arrList = MonitoringUtil.adapterList2(); + } catch ( Exception e ) { + if (logger.isError()){ + logger.error(e.toString()); + } + } + + // ϵ arrList null ƴϸ鼭 迭̰ 0 Exception ߻ + // ʵ ϱ . (2008-06-30) + if( arrList == null || arrList.length == 0 ) { +%> + + <%=eaiSvrInstNm%> + + + + + + + + + +<% + + } else { + int col = arrList[0].length ; + int row = arrList.length ; + for( int i = 0 ; i < row ; i++ ) { + out.println(""); + out.println("" + eaiSvrInstNm + ""); + + for( int j = 0 ; j < col ; j++ ) { + out.println("" + arrList[i][j] + ""); + } + out.println(""); + } + } +%> + + \ No newline at end of file diff --git a/WebContent/agent/host/adapter_socket2_startstop.jsp b/WebContent/agent/host/adapter_socket2_startstop.jsp new file mode 100644 index 0000000..6d7b74e --- /dev/null +++ b/WebContent/agent/host/adapter_socket2_startstop.jsp @@ -0,0 +1,54 @@ +<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> +<%@ page import="com.eactive.eai.adapter.socket2.config.MonitoringUtil"%> +<%@ page import="com.eactive.eai.common.util.CharsetDecoderUtil" %> +<%@ page import="java.util.*,com.eactive.eai.common.util.Logger" %> +<%! + static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT); +%> +<% + // + // Socket2 adapter start/stop command + + String adapterGroupName = request.getParameter("adapterGroupName"); + String adapterName = request.getParameter("adapterName"); + String cmd = request.getParameter("cmd"); + + if( adapterGroupName == null ) { + adapterGroupName = "" ; + } + + if( adapterName == null ) { + adapterName = "" ; + } + + if( cmd == null ) { + cmd = "" ; + } + + + String retMsg = null ; + try { + if( cmd.equals("start") ) { + MonitoringUtil.adapterStart(adapterGroupName, adapterName); + retMsg = "true" ; + } else if( cmd.equals("stop") ) { + MonitoringUtil.adapterStop(adapterGroupName, adapterName); + retMsg = "true" ; + } else { + retMsg = "Unknown command error :" + cmd ; + } + } catch ( Exception e ) { + if (logger.isError()){ + logger.error("MonitoringUtil.adapterStart|adapterStop(" + adapterGroupName + ", " + adapterName + ")" ); + } + //e.printStackTrace(new java.io.PrintWriter(out)); + retMsg = "false" ; + } + + if( retMsg == null ) + retMsg = "" ; + + + + out.println( CharsetDecoderUtil.toKor(retMsg) ); +%> 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 6c36043..e2d424b 100644 --- a/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java +++ b/src/main/java/com/eactive/eai/adapter/controller/ApiAdapterController.java @@ -299,6 +299,4 @@ public class ApiAdapterController implements HttpAdapterServiceKey { 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 5a0df56..a9f1bbe 100644 --- a/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java +++ b/src/main/java/com/eactive/eai/adapter/service/ApiAdapterService.java @@ -309,7 +309,27 @@ public class ApiAdapterService extends HttpAdapterServiceSupport { result = mapper.writeValueAsString(rootNode); } } - + + // KJBank는 요청에 대한 응답 (Sync응답, Aync 에 대한 Ack응답) 에 대하여 암호화 하지 않는다. 무조건 안한다. 따라서 아래부분은 구현은 했지만 사용하지 않는다. + //result = doPostEncryption(result, transactionProp); // jwhong Encrypt + // ASYNC 인 경우 광주은행은 RETURN 해 주는 값들이 수정되어야 한다. JWHONG + /* + 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; diff --git a/src/main/java/com/eactive/eai/authserver/config/AuthorizationServerConfig.java b/src/main/java/com/eactive/eai/authserver/config/AuthorizationServerConfig.java index 33be4d0..9bd1734 100644 --- a/src/main/java/com/eactive/eai/authserver/config/AuthorizationServerConfig.java +++ b/src/main/java/com/eactive/eai/authserver/config/AuthorizationServerConfig.java @@ -104,7 +104,7 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap tokenType = vo.getProperty(PROP_TOKEN_TYPE, "JWT"); } - endpoints.pathMapping("/oauth/token", "/api/v1/oauth/token"); +// endpoints.pathMapping("/oauth/token", "/auth/oauth/v2/token") ; endpoints.authenticationManager(authenticationManager); endpoints.userDetailsService(userDetailsService); diff --git a/src/main/java/com/eactive/eai/authserver/config/OAuthRequestLoggingFilter.java b/src/main/java/com/eactive/eai/authserver/config/OAuthRequestLoggingFilter.java index 59278ca..efb0f18 100644 --- a/src/main/java/com/eactive/eai/authserver/config/OAuthRequestLoggingFilter.java +++ b/src/main/java/com/eactive/eai/authserver/config/OAuthRequestLoggingFilter.java @@ -1,5 +1,6 @@ package com.eactive.eai.authserver.config; +import org.apache.commons.lang3.StringUtils; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; @@ -12,7 +13,7 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Collection; -public class OAuthRequestLoggingFilter extends OncePerRequestFilter { +public class OAuthRequestLoggingFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) @@ -24,9 +25,10 @@ public class OAuthRequestLoggingFilter extends OncePerRequestFilter { data.setGrantType(request.getParameter("grant_type")); data.setScope(request.getParameter("scope")); data.setUsername(request.getParameter("username")); + data.setResource(request.getParameter("resource")); RequestContextData.ThreadLocalRequestContext.set(data); - + filterChain.doFilter(request, response); } finally { RequestContextData.ThreadLocalRequestContext.clear(); diff --git a/src/main/java/com/eactive/eai/authserver/config/RequestContextData.java b/src/main/java/com/eactive/eai/authserver/config/RequestContextData.java index 19815de..20a261a 100644 --- a/src/main/java/com/eactive/eai/authserver/config/RequestContextData.java +++ b/src/main/java/com/eactive/eai/authserver/config/RequestContextData.java @@ -3,12 +3,13 @@ package com.eactive.eai.authserver.config; import lombok.Data; @Data -public class RequestContextData { +public class RequestContextData { private String clientId; private String ipAddress; private String grantType; private String scope; private String username; + private String resource; // Getters and setters diff --git a/src/main/java/com/eactive/eai/authserver/custom/BearerTokenContoller.java b/src/main/java/com/eactive/eai/authserver/custom/BearerTokenContoller.java new file mode 100644 index 0000000..bda62ca --- /dev/null +++ b/src/main/java/com/eactive/eai/authserver/custom/BearerTokenContoller.java @@ -0,0 +1,125 @@ +package com.eactive.eai.authserver.custom; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang3.StringUtils; +import org.json.simple.JSONObject; +import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; + +import com.eactive.eai.adapter.http.dynamic.filter.JwtAuthException; +import com.eactive.eai.authserver.service.OAuth2Manager; +import com.eactive.eai.common.util.Logger; + +@RestController +@RequestMapping("/auth/oauth/v2") +public class BearerTokenContoller { + + public static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT); + private final BearerTokenService tokenService; + + public BearerTokenContoller(BearerTokenService tokenService) { + this.tokenService = tokenService; + } + + // 기본 CA Bearer Token 발급 + @PostMapping("/token") + public ResponseEntity issueCAToken(@RequestParam MultiValueMap req) throws JwtAuthException { + JSONObject resObject = new JSONObject(); + + try { + String clientId = req.getFirst("client_id"); // .get("client_id"); + String grantType = req.getFirst("grant_type"); + if (!StringUtils.equals(grantType, "client_credentials") ) { + throw new JwtAuthException("unsupported_grant_type", "Unsupported grant type"); + } + + ClientDetails clientDetails = OAuth2Manager.getInstance().getClientDeatilsStore().get(clientId); + if (clientDetails == null) { + throw new JwtAuthException("invalid_client", "Bad client credentials(not found)"); + } + + String tokenType = "Bearer"; + String clientSecret = req.getFirst("client_secret"); + String scopes = req.getFirst("scope"); + Long expiresIn = Long.valueOf(clientDetails.getAccessTokenValiditySeconds()); + + String[] reqScopeArr = org.springframework.util.StringUtils.tokenizeToStringArray(scopes, " "); + Set scopeSet = new HashSet(); + for (String scope : reqScopeArr) { + scopeSet.add(scope); + } + veryfyClient(clientDetails, clientSecret, scopeSet); + + String token = tokenService.generateCAToken(clientId, expiresIn, scopeSet); + + Map tokenMap = new HashMap<>(); + tokenMap.put("token_type", tokenType); + tokenMap.put("access_token", token); + tokenMap.put("expires_in", expiresIn); + tokenMap.put("scope", scopes); + // ... and so on for all key-value pairs + resObject.putAll(tokenMap); + + return ResponseEntity.ok(resObject); + } catch (JwtAuthException e) { + logger.error(e); + + JSONObject errorJson = new JSONObject(); + errorJson.put("error", e.getCode()); + errorJson.put("error_description", e.getMessage()); + resObject.putAll(errorJson); + return ResponseEntity.status(401).body(resObject); + } catch (Exception e) { + logger.error(e); + + JSONObject errorJson = new JSONObject(); + errorJson.put("error", "invalid_request"); + errorJson.put("error_description", e.getMessage()); + resObject.putAll(errorJson); + return ResponseEntity.status(500).body(resObject); + } + } + +// // 서비스용 Bearer Token 발급 +// @PostMapping("/service") +// public ResponseEntity issueFileToken(@RequestBody Map req) { +// String fileId = req.get("fileid"); +// +// String token = tokenService.generateFileToken(fileId); +// +// Map tokenMap = new HashMap<>(); +// tokenMap.put("token_type", "Bearer"); +// tokenMap.put("file_token", token); +// tokenMap.put("expires_in", "599"); +// tokenMap.put("expires_on", "1575593514"); +// tokenMap.put("resource", fileId); +// +// return ResponseEntity.ok(tokenMap); +// } + private void veryfyClient(ClientDetails clientDetails, String clientSecret, Set scopeSet) throws JwtAuthException { + if (!StringUtils.equals(clientDetails.getClientSecret(), clientSecret)) { + throw new JwtAuthException("invalid_client", "Bad client credentials(client_secret is empty or not match)"); + } + + if (scopeSet.isEmpty()) { + throw new JwtAuthException("invalid_client", "Bad client credentials(Scope is empty)"); + } + + if (!clientDetails.getScope().containsAll(scopeSet)) { + throw new JwtAuthException("invalid_client", "Bad client credentials(Include unacceptable scope)"); + } + } +} + diff --git a/src/main/java/com/eactive/eai/authserver/custom/BearerTokenFilter.java b/src/main/java/com/eactive/eai/authserver/custom/BearerTokenFilter.java new file mode 100644 index 0000000..d993d30 --- /dev/null +++ b/src/main/java/com/eactive/eai/authserver/custom/BearerTokenFilter.java @@ -0,0 +1,85 @@ +package com.eactive.eai.authserver.custom; + +import java.io.IOException; +import java.util.Arrays; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.json.simple.JSONObject; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import com.eactive.eai.adapter.http.dynamic.filter.JwtAuthException; +import com.eactive.eai.common.util.Logger; + +@Component +public class BearerTokenFilter extends OncePerRequestFilter{ + + public static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT); + private final BearerTokenService tokenService; + + public static final String ERROR_AUTHENTICATION_FAIL = "E.AUTHENTICATION_FAIL"; + public static final String ERROR_AUTHORIZATION_FAIL = "E.AUTHORIZATION_FAIL"; + public static final String ERROR_TOKEN_EXPIRED = "E.TOKEN_EXPIRED"; + + public BearerTokenFilter(BearerTokenService tokenService) { + this.tokenService = tokenService; + } + + @Override + protected void doFilterInternal(HttpServletRequest request, + HttpServletResponse response, + FilterChain filterChain) throws IOException, ServletException { + JSONObject resObject = new JSONObject(); + + try { + String auth = request.getHeader("Authorization"); + + if (auth != null && auth.startsWith("Bearer ")) { + String token = auth.substring(7); + + String clientId = null; + String fileId = null; + + if (tokenService.validateCA(token)) { + clientId = tokenService.getClientIdFromCA(token); + } else { + throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Access token is invalid or expired"); + } + +// if (fileId != null) { +// UsernamePasswordAuthenticationToken authentication = +// new UsernamePasswordAuthenticationToken(fileId, null, Arrays.asList()); +// SecurityContextHolder.getContext().setAuthentication(authentication); +// } + } + + filterChain.doFilter(request, response); + } catch (JwtAuthException jae) { + logger.debug(jae.getMessage()); + + JSONObject errorJson = new JSONObject(); + errorJson.put("error", jae.getCode()); + errorJson.put("error_description", jae.getMessage()); + resObject.putAll(errorJson); + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401 설정 + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().write(resObject.toJSONString()); + } catch (Exception e) { + logger.error(e.getMessage()); + JSONObject errorJson = new JSONObject(); + errorJson.put("error", "invalid_request"); + errorJson.put("error_description", e.getMessage()); + resObject.putAll(errorJson); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); // 500 설정 + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().write(resObject.toJSONString()); + } + } +} + diff --git a/src/main/java/com/eactive/eai/authserver/custom/BearerTokenInfo.java b/src/main/java/com/eactive/eai/authserver/custom/BearerTokenInfo.java new file mode 100644 index 0000000..e5a37fb --- /dev/null +++ b/src/main/java/com/eactive/eai/authserver/custom/BearerTokenInfo.java @@ -0,0 +1,49 @@ +package com.eactive.eai.authserver.custom; + +import java.util.Set; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class BearerTokenInfo { + @JsonProperty("client_id") + private String clientId; + private Long expiresIn; + private Long expiresAt; + private Set scopeSet; + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public Long getExpiresIn() { + return expiresIn; + } + + public void setExpiresIn(Long expiresIn) { + this.expiresIn = expiresIn; + } + + public Long getExpiresAt() { + return expiresAt; + } + + public void setExpiresAt(Long expiresIn) { + this.expiresAt = System.currentTimeMillis() + (expiresIn * 1000); + } + + public Set getScopeSet() { + return scopeSet; + } + + public void setScopeSet(Set scopeSet) { + this.scopeSet = scopeSet; + } + + public boolean isExpired() { + return System.currentTimeMillis() > expiresAt; + } +} diff --git a/src/main/java/com/eactive/eai/authserver/custom/BearerTokenService.java b/src/main/java/com/eactive/eai/authserver/custom/BearerTokenService.java new file mode 100644 index 0000000..3b01368 --- /dev/null +++ b/src/main/java/com/eactive/eai/authserver/custom/BearerTokenService.java @@ -0,0 +1,97 @@ +package com.eactive.eai.authserver.custom; + +import java.security.SecureRandom; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.springframework.stereotype.Service; + +@Service +public class BearerTokenService { + + // CA 토큰 저장소 + private final Map CATokenStore = new ConcurrentHashMap<>(); + + // File 토큰 저장소 + private final Map fileTokenStore = new ConcurrentHashMap<>(); + +// // FileTransfer 토큰 저장소 +// private final Map fileTransferTokenStore = new ConcurrentHashMap<>(); + + public String generateCAToken(String clientId, Long expiresIn, Set scopeSet) { + String token = UUID.randomUUID().toString(); + + BearerTokenInfo CATokenInfo = new BearerTokenInfo(); + CATokenInfo.setClientId(clientId); + CATokenInfo.setExpiresIn(expiresIn); + CATokenInfo.setExpiresAt(expiresIn); + CATokenInfo.setScopeSet(scopeSet); + + CATokenStore.put(token, CATokenInfo); + + return token; + } + + public String generateFileToken(String fileId) { + //String token = UUID.randomUUID().toString().replace("-", ""); + String token = generateTokenString(987); + fileTokenStore.put(token, fileId); + return token; + } + +// public String generateFileTransferToken(String fileId) { +// //String token = UUID.randomUUID().toString().replace("-", ""); +// String token = generateTokenString(654); +// fileTransferTokenStore.put(token, fileId); +// return token; +// } + + public boolean validateCA(String token) { + BearerTokenInfo CATokenInfo = CATokenStore.get(token); + if (CATokenInfo == null) return false; + + if (CATokenInfo.isExpired()) { + CATokenStore.remove(token); + return false; + } + return CATokenStore.containsKey(token); + } + + public boolean validateFile(String token) { + return fileTokenStore.containsKey(token); + } + +// public boolean validateFileTransfer(String token) { +// return fileTransferTokenStore.containsKey(token); +// } + + public String getClientIdFromCA(String token) { + BearerTokenInfo CATokenInfo = CATokenStore.get(token); + return CATokenInfo.getClientId(); + } + + public String getFileIdFromFile(String token) { + return fileTokenStore.get(token); + } + +// public String getFileIdFromFileTransfer(String token) { +// return fileTransferTokenStore.get(token); +// } + + private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + private static final SecureRandom secureRandom = new SecureRandom(); + + public static String generateTokenString(int length) { + // Java 8의 IntStream과 Collectors.joining을 사용한 효율적인 방법 + return IntStream.range(0, length) + .map(i -> secureRandom.nextInt(CHARACTERS.length())) + .mapToObj(CHARACTERS::charAt) + .map(String::valueOf) + .collect(Collectors.joining()); + } +} + diff --git a/src/main/java/com/eactive/eai/authserver/custom/KjbMGOAuth2AccessTokenRequest.java b/src/main/java/com/eactive/eai/authserver/custom/KjbMGOAuth2AccessTokenRequest.java new file mode 100644 index 0000000..dcd880b --- /dev/null +++ b/src/main/java/com/eactive/eai/authserver/custom/KjbMGOAuth2AccessTokenRequest.java @@ -0,0 +1,63 @@ +package com.eactive.eai.authserver.custom; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonProperty; + +@SuppressWarnings("serial") +public class KjbMGOAuth2AccessTokenRequest implements Serializable { + @JsonProperty("grant_type") + private String grantType; + @JsonProperty("client_id") + private String clientId; + @JsonProperty("client_secret") + private String clientSecret; + private String resource; + private String scope; + + public String getGrantType() { + return grantType; + } + + public void setGrantType(String grantType) { + this.grantType = grantType; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public String getClientSecret() { + return clientSecret; + } + + public void setClientSecret(String clientSecret) { + this.clientSecret = clientSecret; + } + + public String getResource() { + return resource; + } + + public void setResource(String resource) { + this.resource = resource; + } + + public String getScope() { + return scope; + } + + public void setScope(String scope) { + this.scope = scope; + } + + @Override + public String toString() { + return "KjbMGOAuth2AccessTokenRequest [grantType=" + grantType + ", clientId=" + clientId + ", clientSecret=" + + clientSecret + ", resource=" + resource + ", scope=" + scope + "]"; + } +} diff --git a/src/main/java/com/eactive/eai/authserver/custom/KjbMGOAuth2AccessTokenResponse.java b/src/main/java/com/eactive/eai/authserver/custom/KjbMGOAuth2AccessTokenResponse.java new file mode 100644 index 0000000..b99ffe1 --- /dev/null +++ b/src/main/java/com/eactive/eai/authserver/custom/KjbMGOAuth2AccessTokenResponse.java @@ -0,0 +1,105 @@ +package com.eactive.eai.authserver.custom; + +import java.io.Serializable; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonInclude.Include; + +@SuppressWarnings("serial") +@JsonInclude(Include.NON_NULL) +public class KjbMGOAuth2AccessTokenResponse implements Serializable { + private String responseCode; + private String responseMessage; + @JsonProperty("access_token") + private String accessToken; + @JsonProperty("refresh_token") + private String refreshToken; + @JsonProperty("token_type") + private String tokenType; + @JsonProperty("expires_in") + private Long expiresIn; + @JsonProperty("expires_on") + private Long expiresOn; + private String resource; + private String scope; + + public String getResponseCode() { + return responseCode; + } + + public void setResponseCode(String responseCode) { + this.responseCode = responseCode; + } + + public String getResponseMessage() { + return responseMessage; + } + + public void setResponseMessage(String responseMessage) { + this.responseMessage = responseMessage; + } + + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + public String getrefreshToken() { + return refreshToken; + } + + public void setrefreshToken(String refreshToken) { + this.refreshToken = refreshToken; + } + + public String getTokenType() { + return tokenType; + } + + public void setTokenType(String tokenType) { + this.tokenType = tokenType; + } + + public Long getExpiresIn() { + return expiresIn; + } + + public void setExpiresIn(Long expiresIn) { + this.expiresIn = expiresIn; + } + + public Long getExpiresOn() { + return expiresOn; + } + + public void setExpiresOn(Long expiresOn) { + this.expiresOn = expiresOn; + } + + public String getResource() { + return resource; + } + + public void setResource(String resource) { + this.resource = resource; + } + + public String getScope() { + return scope; + } + + public void setScope(String scope) { + this.scope = scope; + } + + @Override + public String toString() { + return "KjbMGOAuth2AccessTokenResponse [responseCode=" + responseCode + ", responseMessage=" + responseMessage + + ", accessToken=" + accessToken + ", tokenType=" + tokenType + ", expiresIn=" + expiresIn + + ", refreshToken=" + refreshToken+ ", expiresOn=" + expiresOn+ ", resource=" + resource+ ", scope=" + scope + "]"; + } +} diff --git a/src/main/java/com/eactive/eai/authserver/custom/KjbMGOAuth2Controller.java b/src/main/java/com/eactive/eai/authserver/custom/KjbMGOAuth2Controller.java new file mode 100644 index 0000000..f08be14 --- /dev/null +++ b/src/main/java/com/eactive/eai/authserver/custom/KjbMGOAuth2Controller.java @@ -0,0 +1,288 @@ +package com.eactive.eai.authserver.custom; + +import java.nio.charset.StandardCharsets; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.Principal; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.Signature; +import java.security.spec.X509EncodedKeySpec; +import java.time.LocalDateTime; +import java.util.Base64; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +import javax.crypto.Cipher; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.math.NumberUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint; +import org.springframework.security.oauth2.provider.token.TokenEnhancer; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.eactive.eai.adapter.http.dynamic.filter.JwtAuthException; +import com.eactive.eai.authserver.config.IssueLimitOAuth2Exception; +import com.eactive.eai.authserver.config.AuthorizationServerConfig; +import com.eactive.eai.authserver.config.RequestContextData; +import com.eactive.eai.authserver.dao.TokenIssuanceLogDAO; +import com.eactive.eai.authserver.service.OAuth2Manager; +import com.eactive.eai.authserver.util.BeanUtils; +import com.eactive.eai.authserver.vo.ClientVO; +import com.eactive.eai.common.dao.DAOException; +import com.eactive.eai.common.logger.EAIDBLogControl; +import com.eactive.eai.common.util.Logger; +import com.eactive.eai.common.util.UUID; +import com.eactive.eai.data.entity.onl.authserver.TokenIssuanceLog; + +@Controller +public class KjbMGOAuth2Controller { + public static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT); + + private static final String HEADER_TRACEID = "traceId"; + + private static final String SERVICE_CODE_ACCESS_TOKEN = "00"; // 임시설정 + @Autowired + private TokenIssuanceLogDAO tokenIssuanceLogDAO; + + @RequestMapping(value = "/mapi/oauth2/token2", method = RequestMethod.POST, produces = "application/json; charset=\"UTF-8\"") + @ResponseBody + public KjbMGOAuth2AccessTokenResponse token(@RequestBody KjbMGOAuth2AccessTokenRequest tokenRequest, + HttpServletRequest request, HttpServletResponse response) { + if (logger.isDebug()) { + logger.debug(tokenRequest.toString()); + } + + KjbMGOAuth2AccessTokenResponse responseToken = new KjbMGOAuth2AccessTokenResponse(); + try { + if (!StringUtils.equals(tokenRequest.getGrantType(), "client_credentials")) { + throw new JwtAuthException( + String.format("%d%s%s", HttpStatus.BAD_REQUEST.value(), SERVICE_CODE_ACCESS_TOKEN, "02"), + "Invalid Mandatory Field {grantType}"); + } + + String grantType = tokenRequest.getGrantType(); + String clientId = tokenRequest.getClientId(); + String clientSecret = tokenRequest.getClientSecret(); + + String[] scopeArr = org.springframework.util.StringUtils.tokenizeToStringArray(tokenRequest.getScope(), " "); + Set scopeSet = new HashSet(); + for (String scope : scopeArr) { + scopeSet.add(scope); + } + + String[] resourceArr = org.springframework.util.StringUtils.tokenizeToStringArray(tokenRequest.getResource(), ","); + Set resourceSet = new HashSet(); + for (String resource : resourceArr) { + resourceSet.add(resource); + } + + ClientDetails clientDetails = OAuth2Manager.getInstance().getClientDeatilsStore().get(clientId); + verifyClient(clientDetails, clientId, scopeSet); + + String traceId = UUID.randomUUID().toString().replace("-", ""); + response.setHeader(HEADER_TRACEID, traceId); + + HashMap authorizationParameters = new HashMap(); + authorizationParameters.put(OAuth2Utils.GRANT_TYPE, grantType); + authorizationParameters.put(OAuth2Utils.CLIENT_ID, clientId); + authorizationParameters.put("client_secret", clientSecret); + + Set responseType = new HashSet(); + responseType.add(tokenRequest.getGrantType()); + + OAuth2Request authorizationRequest = new OAuth2Request(authorizationParameters, clientId, null, true, scopeSet, + resourceSet, "", responseType, null); + + Principal principal = new OAuth2Authentication(authorizationRequest, null); + ResponseEntity result = tokenEndpoint().postAccessToken(principal, + authorizationParameters); + OAuth2AccessToken token = result.getBody(); + if(StringUtils.isNotBlank(token.getTokenType()) && StringUtils.equalsIgnoreCase(token.getTokenType(), "bearer")) { + responseToken.setTokenType("Bearer"); + } else { responseToken.setTokenType(token.getTokenType()); } + responseToken.setAccessToken(token.getValue()); + responseToken.setExpiresIn(Long.valueOf(token.getExpiresIn())); + responseToken.setrefreshToken(""); + responseToken.setExpiresOn(System.currentTimeMillis() + (token.getExpiresIn() * 1000)); + responseToken.setScope(tokenRequest.getScope()); + responseToken.setResource(tokenRequest.getResource()); + } catch (JwtAuthException e) { + response.setStatus(NumberUtils.toInt(StringUtils.left(e.getCode(), 3), HttpStatus.UNAUTHORIZED.value())); + responseToken.setResponseCode(e.getCode()); + responseToken.setResponseMessage(e.getMessage()); + } catch (Exception e) { + logger.error(e.getMessage()); + response.setStatus(HttpStatus.UNAUTHORIZED.value()); + responseToken.setResponseCode( + String.format("%d%s%s", HttpStatus.UNAUTHORIZED.value(), SERVICE_CODE_ACCESS_TOKEN, "00")); + responseToken.setResponseMessage("Unauthorized. [Unknown]"); + } + + return responseToken; + } + + private void verifyClient(ClientDetails clientDetails, String clientId, Set scopeSet) + throws JwtAuthException { + + if (StringUtils.isBlank(clientId)) { + throw new JwtAuthException( + String.format("%d%s%s", HttpStatus.BAD_REQUEST.value(), SERVICE_CODE_ACCESS_TOKEN, "02"), + "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 (scopeSet.isEmpty()) { + throw new JwtAuthException( + String.format("%d%s%s", HttpStatus.BAD_REQUEST.value(), SERVICE_CODE_ACCESS_TOKEN, "02"), + "Invalid Mandatory Field {scope}"); + } + + if (!clientDetails.getScope().containsAll(scopeSet)) { + throw new JwtAuthException( + String.format("%d%s%s", HttpStatus.UNAUTHORIZED.value(), SERVICE_CODE_ACCESS_TOKEN, "00"), + "Unauthorized. [Bad client credentials(Include unacceptable scope)]"); + } + + } + + private TokenEndpoint tokenEndpoint() { + return BeanUtils.getBean("tokenEndpoint", TokenEndpoint.class); + } + + private class TokenIssuanceLogEnhancer implements TokenEnhancer { + @Override + public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { + if (!EAIDBLogControl.isEnable()) { + logger.warn("DB logging is disabled. Skipping token issuance logging."); + return accessToken; + } + + String clientId = authentication.getOAuth2Request().getClientId(); + LocalDateTime startDateTime = LocalDateTime.now().minusHours(24); + + int recentTokenCount = tokenIssuanceLogDAO.findRecentLogsForRestrictionCount(clientId, startDateTime); + + try { + ClientVO clientVO = OAuth2Manager.getInstance().getClientInfo(clientId); + int dailyTokenLimit = clientVO.getDailyTokenLimit(); + if (dailyTokenLimit > 0 && recentTokenCount >= dailyTokenLimit) { + throw new IssueLimitOAuth2Exception("Token issuance limit exceeded for this client"); + } + + // JWT 변환 이후의 최종 토큰 값 로깅 + logTokenIssuance(true, false, "Token issued successfully", accessToken.getValue()); + } catch (DAOException e) { + logger.warn("cannot find clientVo - " + clientId); + } + return accessToken; + } + } + + private void logTokenIssuance(boolean isSuccess, boolean isRestrictionExempt, String resultMessage, String accessToken) { + try { + if (!EAIDBLogControl.isEnable()) { + logger.warn("DB logging is disabled. Skipping token issuance logging."); + return; + } + RequestContextData data = RequestContextData.ThreadLocalRequestContext.get(); + OAuth2Manager.getInstance(); + + TokenIssuanceLog log = new TokenIssuanceLog(); + String clientId = data.getClientId(); + log.setClientId(clientId); + + if(StringUtils.isNotBlank(clientId)) { + ClientVO clientVO = OAuth2Manager.getInstance().getClientInfo(clientId); + log.setAppName(clientVO.getClientName()); + log.setOrgId(clientVO.getOrgId()); + log.setOrgName(clientVO.getOrgName()); + } + + log.setGrantType(data.getGrantType()); + log.setScope(data.getScope()); + log.setIpAddress(data.getIpAddress()); + log.setSuccessYn(isSuccess ? "Y" : "N"); + log.setIssuanceDateTime(LocalDateTime.now()); + log.setRestrictionExemptYn(isRestrictionExempt ? "Y" : "N"); + log.setResultMessage(resultMessage); + log.setAccessToken(accessToken); // Add access token value to the log + + tokenIssuanceLogDAO.saveTokenIssuanceLog(log); + } catch (Throwable th) { + logger.error("Error while logging token issuance: " + th.getMessage(), th); + } + } + + public static void main(String[] args) throws Exception { + // First generate a public/private key pair + KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA"); + // generator.initialize(512, new SecureRandom()); + //generator.initialize(1024, new SecureRandom()); + generator.initialize(2048, new SecureRandom()); + KeyPair pair = generator.generateKeyPair(); + + // The private key can be used to sign (not encrypt!) a message. The public key + // holder can then verify the message. + + String message = "sSGJDwlJsel5WeXodzd3J3MQ20KYCZpL|2022-12-21T14:36:19+07:00"; + + // Let's sign our message + Signature privateSignature = Signature.getInstance("SHA256withRSA"); + privateSignature.initSign(pair.getPrivate()); + privateSignature.update(message.getBytes(StandardCharsets.UTF_8)); + System.out.println( + "private key=" + Base64.getEncoder().encodeToString(pair.getPrivate().getEncoded())); + + byte[] signature = privateSignature.sign(); + //System.out.println("signature=" + new String(signature, StandardCharsets.UTF_8)); + System.out.println("signature=" + Base64.getEncoder().encodeToString(signature)); + + // Let's check the signature + Signature publicSignature = Signature.getInstance("SHA256withRSA"); + publicSignature.initVerify(pair.getPublic()); + publicSignature.update(message.getBytes(StandardCharsets.UTF_8)); + boolean isCorrect = publicSignature.verify(signature); + System.out.println("public key=" + Base64.getEncoder().encodeToString(pair.getPublic().getEncoded())); + + System.out.println("Signature correct: " + isCorrect); + + // The public key can be used to encrypt a message, the private key can be used + // to decrypt it. + // Encrypt the message + Cipher encryptCipher = Cipher.getInstance("RSA"); + encryptCipher.init(Cipher.ENCRYPT_MODE, pair.getPublic()); + + byte[] cipherText = encryptCipher.doFinal(message.getBytes(StandardCharsets.UTF_8)); + + // Now decrypt it + Cipher decriptCipher = Cipher.getInstance("RSA"); + decriptCipher.init(Cipher.DECRYPT_MODE, pair.getPrivate()); + + String decipheredMessage = new String(decriptCipher.doFinal(cipherText), StandardCharsets.UTF_8); + + System.out.println(decipheredMessage); + } +} diff --git a/src/main/java/com/eactive/eai/authserver/custom/SecurityConfig.java b/src/main/java/com/eactive/eai/authserver/custom/SecurityConfig.java new file mode 100644 index 0000000..f2a6183 --- /dev/null +++ b/src/main/java/com/eactive/eai/authserver/custom/SecurityConfig.java @@ -0,0 +1,58 @@ +package com.eactive.eai.authserver.custom; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +// +//@Configuration +//@EnableWebSecurity +//public class SecurityConfig { +// +// private final BearerTokenFilter tokenFilter; +// +// public SecurityConfig(BearerTokenFilter tokenFilter) { +// this.tokenFilter = tokenFilter; +// } +// +// @Bean +// public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { +// +// http +// .csrf().disable() +// .authorizeRequests() +// .antMatchers("/auth/token/**").permitAll() +// .anyRequest().authenticated() +// .and() +// .addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class); +// +// return http.build(); +// } +//} +@Configuration +@EnableWebSecurity +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + private final BearerTokenFilter tokenFilter; + + @Autowired + public SecurityConfig(BearerTokenFilter tokenFilter) { + this.tokenFilter = tokenFilter; + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + + http + .csrf().disable() + .authorizeRequests() + .antMatchers("/auth/token/**").permitAll() + .anyRequest().authenticated() + .and() + .addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class); + } +} \ No newline at end of file diff --git a/src/main/java/com/eactive/eai/custom/adapter/app/impl/JwtTokenCreator.java b/src/main/java/com/eactive/eai/custom/adapter/app/impl/JwtTokenCreator.java new file mode 100644 index 0000000..47a4ded --- /dev/null +++ b/src/main/java/com/eactive/eai/custom/adapter/app/impl/JwtTokenCreator.java @@ -0,0 +1,477 @@ +package com.eactive.eai.custom.adapter.app.impl; + +import java.text.ParseException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Properties; +import java.util.Set; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; +//import org.codehaus.jackson.map.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.json.simple.JSONObject; +import org.json.simple.JSONValue; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.util.OAuth2Utils; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.OAuth2Request; +import org.springframework.security.oauth2.provider.TokenRequest; +import org.springframework.security.oauth2.provider.token.DefaultTokenServices; +import org.springframework.security.oauth2.provider.token.TokenEnhancer; +import org.springframework.security.oauth2.provider.token.TokenEnhancerChain; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; +import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; + +import com.eactive.eai.adapter.app.BusinessApplication; +import com.eactive.eai.adapter.http.dynamic.filter.ApiAuthFilter; +import com.eactive.eai.adapter.http.dynamic.filter.JwtAuthException; +//import com.eactive.eai.adapter.http.dynamic.filter.JwtAuthFilter; +import com.eactive.eai.authserver.service.OAuth2Manager; +import com.eactive.eai.authserver.util.BeanUtils; +import com.eactive.eai.authserver.vo.ClientVO; +import com.eactive.eai.common.util.Logger; +//import com.nimbusds.jwt.SignedJWT; + +/** + * JWT 토큰을 발급한다.(인증은 요청시스템에서 수행하고 토큰만 발급) + * + * @author + * + */ +public class JwtTokenCreator implements BusinessApplication { + public static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT); + + private static final boolean VERYFY_CLIENT_SECRET = true; + private static final String[] GRANT_TYPES = { "client_credentials", "authorization_code", "password", + "refresh_token" }; + + @SuppressWarnings("unchecked") + @Override + public Object executeApplication(Properties prop, Object messageBytes, Properties tempProp) throws Exception { + // 응답전문용 Json Object + JSONObject resObject = new JSONObject(); + + try { + if (messageBytes == null) { + throw new Exception("Message is null."); + } + + String message = new String((byte[]) messageBytes); + if (StringUtils.isBlank(message)) { + throw new Exception("Message is empty."); + } + + /** + * { + * "grant_type":"client_credentials", + * "client_id":"WNHZOadBfB9UCPPuq6YArKUW87elXmZX", + * "client_secret":"JhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9", + * "scope":"manage", + * "expires_in":3600, + * "resource_ids":"aaa, bbb", + * "authorities":"ROLE_ADM, ROLE_DEV", + * "user_name":"aaaaaaaaaaaaaa", + * "support_refresh_token_yn": "Y", + * "refresh_token_expires_in":86400, + * "refresh_token":"JhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOj~~", + * "iss":"AZABBB0000", + * "aud":"ZZAAAA0000" + * } + */ + boolean isVerifyClientSecret = VERYFY_CLIENT_SECRET; + // 요청전문 Json Object + JSONObject jsonObject = (JSONObject) JSONValue.parse(message); + + /* 2022.5.25. yseo + * 복합거래여부 확인, 복합거래의 경우 요청전문의 내용을 응답전문에 그대로 복사 + * 복합거래 : 토큰발급 이후 2차 처리를 위한 Outbound Adapter를 다시 호출하는 거래 + * 복합거래 대상 EAIServiceCD는 APP Adapter의 프로퍼티(SVC_CD)에 등록해서 관리. + */ + String svcCds = prop.getProperty("SVC_CD"); + String[] svcCdArr = org.springframework.util.StringUtils.tokenizeToStringArray(svcCds, ","); + Boolean isComplex = ArrayUtils.contains(svcCdArr, tempProp.getProperty("EAISvcCd"))?true:false; + if(isComplex) { + resObject = jsonObject; + } + logger.debug("1. isComplex : [" + isComplex + "]"); + + String grantType = (String) jsonObject.get(OAuth2Utils.GRANT_TYPE); + if (!ArrayUtils.contains(GRANT_TYPES, grantType)) { + throw new JwtAuthException("unsupported_grant_type", "Unsupported grant type"); + } + logger.debug("2. grantType : [" + grantType + "]"); + + String clientId = (String) jsonObject.get(OAuth2Utils.CLIENT_ID); + if (StringUtils.isBlank(clientId)) { + throw new JwtAuthException("invalid_client", "Bad client credentials(client_id is empty)"); + /* clientId에 허용된 grantType인지 확인 2022.05.23 yseo*/ + } else { + veryfyGrantType(clientId, grantType); + } + logger.debug("3. clientId : [" + clientId + "]"); + + /* grantType = "client_credentials" 이면 client_secret 체크 2022.05.23 yseo + * Mydata 관련해서는 무조건 체크해야함. + */ +// if (!StringUtils.equalsIgnoreCase(grantType, "client_credentials")) isVerifyClientSecret = false; + if (isVerifyClientSecret) { + String clientSecret = (String) jsonObject.get("client_secret"); + if (StringUtils.isBlank(clientSecret)) { + throw new JwtAuthException("invalid_client", "Bad client credentials(client_secret is empty)"); + } + veryfyClientSecret(clientId, clientSecret); + logger.debug("4. clientSecret : [" + clientSecret + "]"); + } + + Set scopeSet = assignScope((String) jsonObject.get(OAuth2Utils.SCOPE)); + if (scopeSet == null || scopeSet.size() == 0) { + if (!StringUtils.equals(grantType, "refresh_token")) { + throw new Exception("scope is empty."); + } + } + logger.debug("5. scopeSet : [" + scopeSet + "]"); + + Set resourceIdSet = assignResourceIds((String) jsonObject.get("resource")); + Set authoritiesSet = assignAuthorities((String) jsonObject.get("authorities")); + + String userName = (String) jsonObject.get("user_name"); + if (StringUtils.equals(grantType, "password") || StringUtils.equals(grantType, "authorization_code")) { + if (StringUtils.isBlank(userName)) { + throw new Exception("user_name is empty."); + } + } + logger.debug("6. userName : [" + userName + "]"); + + /* 요청정보에 expires_in(토큰유효기간) 값이 없는 경우, client정보에 등록된 유효기간 찾아 대체 2022.05.23 yseo*/ + String expIn = String.valueOf(jsonObject.get(OAuth2AccessToken.EXPIRES_IN)); + Long expiresIn = null; + if (StringUtils.isNumeric(expIn)) { + expiresIn = Long.parseLong(expIn); + } else if (StringUtils.isBlank(expIn) || StringUtils.equalsIgnoreCase("null", expIn)) { + expiresIn = assignDefaultExpiresIn(clientId, "expires_in"); + } else { + throw new Exception("expires_in is not numeric."); + } + logger.debug("7. expiresIn : [" + expIn + "]"); +// Long expiresIn = (Long) jsonObject.get(OAuth2AccessToken.EXPIRES_IN); +// if (expiresIn == null) { +// expiresIn = assignDefaultExpiresIn(clientId, "expires_in"); +// } + + boolean supportRefreshToken = BooleanUtils.toBoolean((String) jsonObject.getOrDefault("support_refresh_token_yn", "N")); + /* 요청정보에 refresh_token_expires_in(리프레시토큰유효기간) 값이 없는 경우, client정보에 등록된 유효기간 찾아 대체 2022.05.23 yseo*/ + String refreshExpIn = String.valueOf(jsonObject.get("refresh_token_expires_in")); + Long refreshTokenExpiresIn = null; + if (supportRefreshToken && StringUtils.isNumeric(refreshExpIn)) { + refreshTokenExpiresIn = Long.parseLong(refreshExpIn); + } else if (supportRefreshToken && (StringUtils.isBlank(refreshExpIn) || StringUtils.equalsIgnoreCase("null", refreshExpIn))) { + refreshTokenExpiresIn = assignDefaultExpiresIn(clientId, "refresh_token_expires_in"); + } else if (supportRefreshToken) { + throw new Exception("refresh_token_expires_in is not numeric."); + } + logger.debug("8. refreshTokenExpiresIn : [" + refreshExpIn + "]"); +// Long refreshTokenExpiresIn = (Long) jsonObject.get("refresh_token_expires_in"); +// if (supportRefreshToken && refreshTokenExpiresIn == null) { +// refreshTokenExpiresIn = assignDefaultExpiresIn(clientId, "refresh_token_expires_in"); +// } + + String refreshToken = (String) jsonObject.get("refresh_token"); + if (StringUtils.equals(grantType, "refresh_token") && StringUtils.isBlank(refreshToken)) { + throw new JwtAuthException("invalid_token", "refresh_token is empty."); + } + logger.debug("9. refreshToken : [" + refreshToken + "]"); + + String iss = (String) jsonObject.get("iss"); +// if (StringUtils.isBlank(iss)) { +// iss = assignDefaultStringValue(clientId, "iss"); +// } +// logger.debug("10. iss : [" + iss + "]"); +// + String aud = (String) jsonObject.get("aud"); +// if (StringUtils.isBlank(aud)) { +// aud = assignDefaultStringValue(clientId, "aud"); +// } +// logger.debug("11. aud : [" + aud + "]"); + + String tokenStr = createToken(grantType, clientId, scopeSet, resourceIdSet, authoritiesSet, userName, expiresIn, + supportRefreshToken, refreshTokenExpiresIn, refreshToken, iss, aud); +// logger.debug("#####created tokenStr==>"+tokenStr); + + //20211122 bearer -> Bearer로 변환철. mydata api준수 + JSONObject jsonObj = (JSONObject) JSONValue.parse(tokenStr); + String tokenType = (String)jsonObj.get("token_type"); + if(StringUtils.isNotBlank(tokenType) && StringUtils.equalsIgnoreCase(tokenType, "bearer")) { + jsonObj.put("token_type","Bearer"); + } + jsonObj.remove("jti"); + jsonObj.put("resource", (String) jsonObject.get("resource")); + if (StringUtils.equals(grantType, "password") || StringUtils.equals(grantType, "authorization_code")) { + jsonObj.put("refresh_token_expires_in", refreshTokenExpiresIn-1); + } + tokenStr = jsonObj.toJSONString(); + logger.debug("##### Bearer checked tokenStr==>"+tokenStr); + + // 복합거래의 경우 발급된 토큰정보를 "TOKEN_DATAGROUP" 그룹으로 추가 + if(isComplex) { + resObject.put("TOKEN_DATAGROUP", jsonObj); + } else { + resObject.putAll(jsonObj); + } + String resStr = resObject.toJSONString(); + + return resStr.getBytes(); + } catch (JwtAuthException e) { + logger.error(e); + + JSONObject errorJson = new JSONObject(); + errorJson.put("error", e.getCode()); + errorJson.put("error_description", e.getMessage()); + resObject.putAll(errorJson); + return resObject.toJSONString().getBytes(); + } catch (Exception e) { + logger.error(e); + + JSONObject errorJson = new JSONObject(); + errorJson.put("error", "invalid_request"); + errorJson.put("error_description", e.getMessage()); + resObject.putAll(errorJson); + return resObject.toJSONString().getBytes(); + } + } + + private Set assignResourceIds(String resourceIds) throws Exception { + if (StringUtils.isBlank(resourceIds)) { + return null; + } + + String[] arr = org.springframework.util.StringUtils.tokenizeToStringArray(resourceIds, ","); + Set resourceIdSet = new HashSet(); + for (String resourceId : arr) { + resourceIdSet.add(resourceId); + } + + return resourceIdSet; + } + + private void veryfyGrantType(String clientId, String grantType) throws JwtAuthException { + ClientDetails details = OAuth2Manager.getInstance().getClientDeatilsStore().get(clientId); + if (details == null) { + throw new JwtAuthException("invalid_client", "Bad client credentials(not found)"); + } + + if (!details.getAuthorizedGrantTypes().contains(grantType)) { + throw new JwtAuthException("unsupported_grant_type", "Unsupported grant type for ClientID"); + } + } + + private void veryfyClientSecret(String clientId, String clientSecret) throws JwtAuthException { + ClientDetails details = OAuth2Manager.getInstance().getClientDeatilsStore().get(clientId); + if (details == null) { + throw new JwtAuthException("invalid_client", "Bad client credentials(not found)"); + } + + if (!StringUtils.equals(details.getClientSecret(), clientSecret)) { + throw new JwtAuthException("invalid_client", "Bad client credentials"); + } + } + + private Long assignDefaultExpiresIn(String clientId, String flag) throws JwtAuthException { + ClientDetails details = OAuth2Manager.getInstance().getClientDeatilsStore().get(clientId); + Long retLong = null; + if (details == null) { + throw new JwtAuthException("invalid_client", "Bad client credentials(not found)"); + } + + if (StringUtils.equals(flag, "expires_in") && StringUtils.isNotBlank(details.getAccessTokenValiditySeconds().toString())) { + retLong = new Long(details.getAccessTokenValiditySeconds()); + } else if (StringUtils.equals(flag, "refresh_token_expires_in") && StringUtils.isNotBlank(details.getRefreshTokenValiditySeconds().toString())) { + retLong = new Long(details.getRefreshTokenValiditySeconds()); + } else { + throw new JwtAuthException("invalid_client", "Bad expires_in/refresh_token_expires_in(not found)"); + } + return retLong; + } + + private String assignDefaultStringValue(String clientId, String flag) throws Exception { + ClientVO client = (ClientVO) OAuth2Manager.getInstance().getClientDeatilsStore().get(clientId); + String retStr = ""; + if (client == null) { + throw new JwtAuthException("invalid_client", "Bad client credentials(not found)"); + } + + if (StringUtils.equals(flag, "iss") && StringUtils.isNotBlank(client.getIssuer())) { + retStr = client.getIssuer(); + } else if (StringUtils.equals(flag, "aud") && StringUtils.isNotBlank(client.getAudience())) { + retStr = client.getAudience(); + } else { + throw new Exception("iss/aud is null."); + } + logger.info("===================>"+flag+" : ["+retStr+"]"); + return retStr; + } + + private Set assignScope(String scopes) throws Exception { + if (StringUtils.isBlank(scopes)) { + return new HashSet(); + } + + String[] arr = org.springframework.util.StringUtils.tokenizeToStringArray(scopes, " "); + Set scopeSet = new HashSet(); + for (String scope : arr) { + scopeSet.add(scope); + } + + return scopeSet; + } + + private Set assignAuthorities(String authorities) throws Exception { + if (StringUtils.isBlank(authorities)) { + return new HashSet(); + } + + String[] arr = org.springframework.util.StringUtils.tokenizeToStringArray(authorities, ","); + Set authoritiesSet = new HashSet(); + for (String authority : arr) { + authoritiesSet.add(new SimpleGrantedAuthority(authority)); + } + + return authoritiesSet; + } + + private String createToken(String grantType, String clientId, Set scopeSet, Set resourceIdSet, + Set authoritiesSet, String userName, Long expiresIn, boolean supportRefreshToken, + Long refreshTokenExpiresIn, String refreshToken, String issuer, String audience) throws Exception { + HashMap authorizationParameters = new HashMap(); + authorizationParameters.put(OAuth2Utils.GRANT_TYPE, grantType); + authorizationParameters.put(OAuth2Utils.CLIENT_ID, clientId); +// authorizationParameters.put("iss", issuer); +// authorizationParameters.put("aud", audience); + if (StringUtils.equals(grantType, "password") || StringUtils.equals(grantType, "authorization_code")) { + authorizationParameters.put("user_name", userName); + } + + Set responseType = new HashSet(); + responseType.add(grantType); + + OAuth2Request authorizationRequest = new OAuth2Request(authorizationParameters, clientId, authoritiesSet, true, + scopeSet, resourceIdSet, "", responseType, null); + + Authentication authentication = null; + if (StringUtils.equals(grantType, "password") || StringUtils.equals(grantType, "authorization_code")) { + User userPrincipal = new User(userName, "", true, true, true, true, authoritiesSet); + authentication = new UsernamePasswordAuthenticationToken(userPrincipal, null, authoritiesSet); + } + + OAuth2Authentication authenticationRequest = new OAuth2Authentication(authorizationRequest, authentication); + authenticationRequest.setAuthenticated(true); + + DefaultTokenServices tokenServices = createDefaultTokenServices(supportRefreshToken, expiresIn, + refreshTokenExpiresIn); + OAuth2AccessToken accessToken = null; + if (StringUtils.equals(grantType, "refresh_token")) { + tokenServices.setReuseRefreshToken(true); + TokenRequest tokenRequest = new TokenRequest(authorizationParameters, clientId, scopeSet, grantType); + accessToken = tokenServices.refreshAccessToken(refreshToken, tokenRequest); + } else { + accessToken = tokenServices.createAccessToken(authenticationRequest); + } + + logger.debug("accessToken=" + accessToken.toString()); + + return new ObjectMapper().writeValueAsString(accessToken); + } + + private DefaultTokenServices createDefaultTokenServices(boolean supportRefreshToken, Long expiresIn, + Long refreshTokenExpiresIn) throws Exception { + TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain(); + tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer(), accessTokenConverter())); + + DefaultTokenServices tokenServices = new DefaultTokenServices(); + tokenServices.setTokenStore(tokenStore()); + tokenServices.setSupportRefreshToken(supportRefreshToken); + tokenServices.setTokenEnhancer(tokenEnhancerChain); + if (expiresIn != null) { + tokenServices.setAccessTokenValiditySeconds(expiresIn.intValue()); + } + if (supportRefreshToken && refreshTokenExpiresIn != null) { + tokenServices.setRefreshTokenValiditySeconds(refreshTokenExpiresIn.intValue()); + } + return tokenServices; + } + + private TokenEnhancer tokenEnhancer() { +// return BeanUtils.getBean("tokenEnhancer", TokenEnhancer.class); + return (TokenEnhancer) accessTokenConverter(); + } + + private JwtAccessTokenConverter accessTokenConverter() { + return BeanUtils.getBean("jwtAccessTokenConverter", JwtAccessTokenConverter.class); + } + + private TokenStore tokenStore() { + return new JwtTokenStore((JwtAccessTokenConverter) accessTokenConverter()); + } + + public static void main(String args[]){ + + + +// String token = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImRlZmF1bHRfc3NsX2tleSJ9.ew0KICAiaXNzIjogIkExQUFFUjAwMDAiLA0KICAiYXVkIjoiWlZBQUVNMDAwMCIsDQogICJqdGkiOiJlYmI4NmUyMi03YzZmLTQzZDItOTZiMy05NjU0MTAyZTE1M2MiLA0KICAiZXhwIjoiMTYzNjk2ODcwOSIsDQogICJzY29wZSI6ImJhbmsubGlzdCINCn0.nF0JeCHJHn7yBzhjEnge_Eqi0aAeD_WTt0iUB2V2VPJV9zWgMW-Npr3fCXlmYP5HoTjeQES5ftrxWLlLMaxRPHDKWwafgwLm3eQt9r_x_j0PRn-KpoZ9xTWy3oKCQvP0DN0IQepLZfM214nCrjdSPCV17oUS03cBW0lIDmXeROSR2auAMZvkSQqF74E_QLEKF3XLk0MM3Jz4nZp1bBj3PfJyCxjy2ibp12TN0vHccGmSItqANsbeVn0sQybdIraNzb9bptLwWe8WYyn3XugEA9-bavPOSPwrGgLENBnHnzWj1L8yS0rXuEjydCwf6HMAbpNVHQpicM0Q3xdl5W1PBA"; +// String[] components = token.split("\\s"); + + //String r "refresh_token_expires_in":"604800","refresh_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImRlZmF1bHRfc3NsX2tleSJ9.ew0KICAiaXNzIjogIkExQUFFUjAwMDAiLA0KICAiYXVkIjoiWlZBQUVNMDAwMCIsDQogICJqdGkiOiIwMzI5Y2M3Zi04Y2U2LTQxNzQtYTc5Ny1mMWRjNjg1ZmM5NDAiLA0KICAiZXhwIjoiMTYzNjk2ODcwOSINCn0.dQx6kWm1JCEgueZjUsQJYNDBu2i4P1-jVLKgUH6aX2aBFunlUBtk_zMMFIJb3OvQpz8qPc9xhs1MkM2YHdpJlNleHY3GhhjiQMfYeiCU9yOzv-zuyvOY1pCO0McmHJNdFcxoQfHHFNm4yFay3dOAFE0Z3FQ74nwxrgnzKSucrHCKyGz0pHdLWnWxHNrJMZ4NmaSyPRxU3qxdWFe1soxqgTqpW_SQkTl3D5SWXgevc6zihPPpFhCSOJ39RrJlIVSH1IY5NRAm71AoaZ6ooLsLvPNED3Z7rG-g9coKEU_DASeCNslRZrP0D3azqswFeu-np3zFZUTrgP_TNT6FFReEnA"; + try { + JwtTokenCreator jtc = new JwtTokenCreator(); +// String me="\"d\""; + String message= "{\"refresh_token_expires_in\":\"86400\",\"refresh_token\":null,\"grant_type\":\"authorization_code\",\"support_refresh_token_in\":\"Y\",\"user_name\":\"aaa\",\"scope\":\"bank.list\",\"expires_in\":\"3600\",\"client_id\":\"ZZAAAAPacQmv3ZVhtPISDSA9jb9AWjak\"}"; + JSONObject jsonObject = (JSONObject) JSONValue.parse(message); + String grantType = (String) jsonObject.get(OAuth2Utils.GRANT_TYPE); + String clientId = (String) jsonObject.get(OAuth2Utils.CLIENT_ID); +// String clientSecret = (String) jsonObject.get("client_secret"); + Set scopeSet; + + Properties prop = null; + byte[] msgBytes = null; + msgBytes = message.getBytes(); + jtc.executeApplication(prop, msgBytes, prop); + +// scopeSet = jtc.assignScope((String) jsonObject.get(OAuth2Utils.SCOPE)); +// +// +// Set resourceIdSet = jtc.assignResourceIds((String) jsonObject.get("resource_ids")); +// Set authoritiesSet = jtc.assignAuthorities((String) jsonObject.get("authorities")); +// +// String userName = (String) jsonObject.get("user_name"); +// +// +// Long expiresIn = Long.parseLong(jsonObject.get(OAuth2AccessToken.EXPIRES_IN).toString()); +// Long refreshTokenExpiresIn = Long.parseLong(jsonObject.get("refresh_token_expires_in").toString()); +//// Long expiresIn = (Long) jsonObject.get(OAuth2AccessToken.EXPIRES_IN); +//// Long refreshTokenExpiresIn = (Long) jsonObject.get("refresh_token_expires_in"); +// boolean supportRefreshToken = BooleanUtils +// .toBoolean((String) jsonObject.getOrDefault("support_refresh_token_yn", "Y")); +// +// String refreshToken = (String) jsonObject.get("refresh_token"); +// +// jtc.createToken( grantType, clientId, scopeSet, resourceIdSet,authoritiesSet, userName, expiresIn, supportRefreshToken, +// refreshTokenExpiresIn, refreshToken); + + } catch (ParseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/eactive/eai/custom/message/GUIDGeneratorKJB.java b/src/main/java/com/eactive/eai/custom/message/GUIDGeneratorKJB.java new file mode 100644 index 0000000..71f0dc2 --- /dev/null +++ b/src/main/java/com/eactive/eai/custom/message/GUIDGeneratorKJB.java @@ -0,0 +1,83 @@ +package com.eactive.eai.custom.message; + +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; + +import org.apache.commons.lang3.StringUtils; + +import com.eactive.eai.common.server.Keys; +import com.eactive.eai.common.util.StringUtil; +import com.eactive.eai.common.util.UUID; + +/** + * 1. 기능 : UUID Generation Class 2. 처리 개요 : * - 3. 주의사항 + * + * @author : + * @version : v 1.0.0 + * @see : 관련 기능을 참조 + * @since : : + */ +public final class GUIDGeneratorKJB { + + private static final DateTimeFormatter SDF_YYYYMMDDHHMMSS = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); + + /* + * 그룹사코드(3) + 호스트명(8) + 서버구분번호(2) + 일자(8) + 전문생성시간(6) + 일련번호(6) + 시스템경로번호(3, '001') + */ + + public static final int GUID_LENGTH = 33; // 시스템경로번호 제외부분 + + /** + * 1. 기능 : Private 생성자 2. 처리 개요 : - 3. 주의사항 - Instance 생성하지 못함 + **/ + private GUIDGeneratorKJB() { + } + + public synchronized static String getGUID(String groupCmpCd) { + if (StringUtils.isEmpty(groupCmpCd)) groupCmpCd = "034"; //광주은행 그룹회사코드 "034" + + String nowDateTime = SDF_YYYYMMDDHHMMSS.format(ZonedDateTime.now()); + String strSeq = StringUtils.leftPad(String.valueOf(seq), 6, '0') ; + String guid = groupCmpCd + UNIQUE_NUM + nowDateTime + strSeq + "001"; + + seq++; + if (seq > 999999) { + seq = 1; + } + + return guid; + } + + private static String UNIQUE_NUM; + private static int seq = 1; + static { + String hostname = ""; + try { + hostname = java.net.InetAddress.getLocalHost().getHostName(); + } + catch(Exception e) { + hostname = "________"; + } + + if(hostname.getBytes().length != 8) { + if(hostname.getBytes().length < 8) { + hostname = StringUtils.leftPad(hostname, 8, '_'); + } else if(hostname.getBytes().length > 8) { + hostname = StringUtils.substring(hostname, 0, 8); + } + } + + String serverName = System.getProperty(Keys.SERVER_KEY); + String instid = "00"; + if(serverName != null && serverName.length() > 2) { + instid = serverName.substring(serverName.length()-2, serverName.length()); + } + + UNIQUE_NUM = hostname.toUpperCase() + instid; + } + + public static void main(String[] args) { + String guid = getGUID("051"); + System.out.println("[" + guid.length() + "]" + guid); + } +} \ No newline at end of file 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 diff --git a/src/main/java/com/eactive/eai/custom/message/InterfaceMapperKJB.java b/src/main/java/com/eactive/eai/custom/message/InterfaceMapperKJB.java new file mode 100644 index 0000000..a28ec4f --- /dev/null +++ b/src/main/java/com/eactive/eai/custom/message/InterfaceMapperKJB.java @@ -0,0 +1,202 @@ +package com.eactive.eai.custom.message; + +import org.apache.commons.lang3.StringUtils; + +import com.eactive.eai.common.server.EAIServerManager; +import com.eactive.eai.common.util.StringUtil; +import com.eactive.eai.message.StandardMessage; +import com.eactive.eai.message.service.DefaultInterfaceMapper; +import com.ext.eai.common.stdmessage.STDMessageKeys; + +@SuppressWarnings("serial") +public class InterfaceMapperKJB extends DefaultInterfaceMapper { + private static String SESSION_ID = "INTERFACE_COMMON.MCI_SESN_ID"; + private static String INSTANCE_ID = "INTERFACE_COMMON.MCI_INSTNC_ID"; + + @Override + public String getEaiSvcCode(StandardMessage standardMessage) { + String eaiSvcCode = null; + String interfaceId = getInterfaceId(standardMessage); + String returnType = getSendRecvDivision(standardMessage); // S | R + String inExDivision = getInExDivision(standardMessage); // 1 | 2 + if (interfaceId == null) + interfaceId = ""; + interfaceId = interfaceId.trim(); + + // TODO : site에 맞게 조합해야 함. + eaiSvcCode = interfaceId + returnType + StringUtils.defaultString(inExDivision); + return eaiSvcCode; + } + + @Override + public void setGuid(StandardMessage standardMessage, String guid) { + if (guid == null) + throw new RuntimeException("guid is null"); + if (guid.length() != 36) + throw new RuntimeException("The length of guid is not 36"); + setItemValue(standardMessage, getPath(GUID), guid); + } + + @Override + public String getGuid(StandardMessage standardMessage) { + String guid = getItemValue(standardMessage, getPath(GUID)); + if (guid.length() == 36) { + guid = guid.substring(0, 33); + } + return guid; + } + + @Override + public String getGuidSeq(StandardMessage standardMessage) { + String guidseq = null; + String guid = getItemValue(standardMessage, getPath(GUID)); + if (guid.length() == 36) { + guidseq = guid.substring(33); + } else { + guidseq = "000"; + } + return guidseq; + } + + @Override + public void setGuidSeq(StandardMessage standardMessage, String guidSeq) { + setItemValue(standardMessage, getPath(GUID), getGuid(standardMessage) + guidSeq); + } + + @Override + public String getOrgGuid(StandardMessage standardMessage) { + String orgGuid = getItemValue(standardMessage, getPath(GUID_ORG)); + if (orgGuid.length() == 36) { + orgGuid = orgGuid.substring(0, 33); + } + return orgGuid; + } + + @Override + public void setOrgGuid(StandardMessage standardMessage, String orgGuid) { + if (orgGuid.length() == 36) { + orgGuid = orgGuid.substring(0, 33); + } + setItemValue(standardMessage, getPath(GUID_ORG), orgGuid); + } + + @Override + public String nextGuidSeq(StandardMessage standardMessage) { + String guidSeq = getGuidSeq(standardMessage); + if (guidSeq == null) + return ""; + int seq = 0; + try { + seq = Integer.parseInt(guidSeq) + 1; + } catch (NumberFormatException e) { + seq = 1; + } + guidSeq = StringUtil.stringFormat(Integer.toString(seq), true, '0', 3); + setGuidSeq(standardMessage, guidSeq); + return guidSeq; + } + + /** + * 표준전문의 복원은 COMMON.ORTR_RESTR_YN 의 value는 (Y/N) 엔진에서 복원여부 의 value는 (1/0) + */ + @Override + public String getRecoverYn(StandardMessage standardMessage) { + String data = getItemValue(standardMessage, getPath(RECOVER_YN)); + if ("Y".equals(data)) { + return "1"; + } else { + return "0"; + } + } + + @Override + public void setRecoverYn(StandardMessage standardMessage, String recoverYn) { + if ("1".equals(recoverYn)) { + setItemValue(standardMessage, getPath(RECOVER_YN), "Y"); + } else { + setItemValue(standardMessage, getPath(RECOVER_YN), "N"); + } + } + + @Override + public String getInstCode(StandardMessage standardMessage) { + EAIServerManager server = EAIServerManager.getInstance(); + if (server != null && server.isMCI()) { + return getItemValue(standardMessage, INSTANCE_ID); + } else { + return ""; + } + } + + @Override + public void setInstCode(StandardMessage standardMessage, String instCode) { + EAIServerManager server = EAIServerManager.getInstance(); + if (server != null && server.isMCI()) { + setItemValue(standardMessage, INSTANCE_ID, instCode); + } + } + + @Override + public String getSessionId(StandardMessage standardMessage) { + EAIServerManager server = EAIServerManager.getInstance(); + if (server != null && server.isMCI()) { + return getItemValue(standardMessage, SESSION_ID); + } else { + return ""; + } + } + + @Override + public void setSessionId(StandardMessage standardMessage, String sessionId) { + EAIServerManager server = EAIServerManager.getInstance(); + if (server != null && server.isMCI()) { + setItemValue(standardMessage, SESSION_ID, sessionId); + } + } + + + /* + * 엔진 에서는 public static final String RESPONSE_TYPE_CODE_N = "0";//정상(normal) + * public static final String RESPONSE_TYPE_CODE_E = "1";//오류(error) + */ + @Override + public void setResponseType(StandardMessage standardMessage, String responseType) { + if (responseType != null && (STDMessageKeys.RESPONSE_TYPE_CODE_N.equals(responseType) + || STDMessageKeys.RESPONSE_TYPE_CODE_E.equals(responseType))) { + if (STDMessageKeys.RESPONSE_TYPE_CODE_N.equals(responseType)) { + setItemValue(standardMessage, getPath(RESPONSE_TYPE), "NR"); + } else { + setItemValue(standardMessage, getPath(RESPONSE_TYPE), "ER"); + } + } else { + setItemValue(standardMessage, getPath(RESPONSE_TYPE), responseType); + } + + } + + @Override + public String getInterfaceId(StandardMessage standardMessage) { + String interfaceId = getItemValue(standardMessage, getPath(INTERFACE_ID)); + if (interfaceId == null) + return ""; + interfaceId = interfaceId.trim(); + return interfaceId; + } + + @Override + public String getReqSysCode(StandardMessage standardMessage) { + // apiPath의 값에서 추출할 예정 : serviceId = api_path + String apiPath = getItemValue(standardMessage, getPath(SERVICE_ID)); + if (apiPath != null) { + String[] split = apiPath.split("/"); + if (split.length > 2) { + String route = split[1].toUpperCase(); + if (route.length() > 3) { + route = route.substring(0, 3); + } + return route; + } + } + return null; + } +} \ No newline at end of file