diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/ApiAuthFilter.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/ApiAuthFilter.java index 2babcee..590da9b 100644 --- a/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/ApiAuthFilter.java +++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/ApiAuthFilter.java @@ -1,6 +1,7 @@ package com.eactive.eai.adapter.http.dynamic.filter; import com.eactive.eai.adapter.http.dynamic.HttpAdapterServiceSupport; +import com.eactive.eai.authserver.service.BearerTokenInfo; //import com.eactive.eai.authserver.vo.BearerTokenInfo; //import com.eactive.eai.authserver.custom.BearerTokenService; import com.eactive.eai.authserver.service.OAuth2Manager; @@ -9,6 +10,7 @@ import com.eactive.eai.common.message.EAIMessage; import com.eactive.eai.common.message.EAIMessageManager; import com.eactive.eai.common.property.PropGroupVO; import com.eactive.eai.common.property.PropManager; +import com.eactive.eai.common.session.SessionManager; import com.eactive.eai.common.stdmessage.STDMessageManager; import com.eactive.eai.common.util.Logger; import com.eactive.eai.common.util.StringUtil; @@ -113,7 +115,7 @@ public class ApiAuthFilter implements HttpAdapterFilter { switch (eaiMessage.getAuthType()){ case "oauth": try { - String token = ApiAuthFilter.extractJWTToken(request); + String token = extractBearerToken(request); SignedJWT signedJWT = SignedJWT.parse(token); if (signedJWT.getJWTClaimsSet().getExpirationTime() == null) { @@ -169,6 +171,21 @@ public class ApiAuthFilter implements HttpAdapterFilter { prop.setProperty(HttpAdapterServiceSupport.PROPERTIES_NAME_CLIENT_ID, apiKey); isPassScope = true; break; + case "ca": + String token = extractBearerToken(request); + BearerTokenInfo bearerTokenInfo = SessionManager.getInstance().getCAToken(token); + if ( bearerTokenInfo != null ) { + if( bearerTokenInfo.isExpired() ) { + SessionManager.getInstance().removeCAToken(token); + throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "expried API key \""+token+"\" in Http Authrozation Header"); + } + prop.setProperty(HttpAdapterServiceSupport.PROPERTIES_NAME_CLIENT_ID, bearerTokenInfo.getClientId()); + isPassScope = true; + } + else { + throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "Invalid or missing API key \""+token+"\" in Http Authrozation Header"); + } + break; case "none": return message; } @@ -276,7 +293,7 @@ public class ApiAuthFilter implements HttpAdapterFilter { return false; } - public static String extractJWTToken(HttpServletRequest request) throws JwtAuthException { + public static String extractBearerToken(HttpServletRequest request) throws JwtAuthException { String authorization = request.getHeader("Authorization"); if (StringUtils.isBlank(authorization)) { throw new JwtAuthException(ERROR_AUTHENTICATION_FAIL, "No have header info: Authorization"); diff --git a/src/main/java/com/eactive/eai/authserver/service/BearerTokenInfo.java b/src/main/java/com/eactive/eai/authserver/service/BearerTokenInfo.java new file mode 100644 index 0000000..390ad6d --- /dev/null +++ b/src/main/java/com/eactive/eai/authserver/service/BearerTokenInfo.java @@ -0,0 +1,49 @@ +package com.eactive.eai.authserver.service; + +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/service/BearerTokenService.java b/src/main/java/com/eactive/eai/authserver/service/BearerTokenService.java new file mode 100644 index 0000000..f4b29d6 --- /dev/null +++ b/src/main/java/com/eactive/eai/authserver/service/BearerTokenService.java @@ -0,0 +1,73 @@ +package com.eactive.eai.authserver.service; + +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 javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import com.eactive.eai.common.session.SessionManager; +import com.eactive.eai.common.session.SessionManagerForIgnite; + +@Service +public class BearerTokenService { + + + + + 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); + + SessionManager.getInstance().putCAToken(token, CATokenInfo); + + return token; + } + + public boolean validateCA(String token) { + BearerTokenInfo CATokenInfo = SessionManager.getInstance().getCAToken(token); + if (CATokenInfo == null) return false; + + if (CATokenInfo.isExpired()) { + SessionManager.getInstance().removeCAToken(token); + return false; + }else { + return true; + } + } + + public String getClientIdFromCA(String token) { + BearerTokenInfo CATokenInfo = SessionManager.getInstance().getCAToken(token); + return CATokenInfo.getClientId(); + } + +// 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/common/session/SessionManager.java b/src/main/java/com/eactive/eai/common/session/SessionManager.java index fcf007a..acfa0f1 100644 --- a/src/main/java/com/eactive/eai/common/session/SessionManager.java +++ b/src/main/java/com/eactive/eai/common/session/SessionManager.java @@ -1,5 +1,6 @@ package com.eactive.eai.common.session; +import com.eactive.eai.authserver.service.BearerTokenInfo; import com.eactive.eai.common.lifecycle.Lifecycle; import com.eactive.eai.common.lifecycle.LifecycleException; import com.eactive.eai.common.lifecycle.LifecycleListener; @@ -58,6 +59,7 @@ public abstract class SessionManager implements Lifecycle { public static final String USERID_CAHCE_NAME = "convertUserIdSession"; public static final String WEBSOCKER_CAHCE_NAME = "webSocketTimeout"; public static final String TERMINAL_CAHCE_NAME = "terminalSession"; + public static final String CAGATEWAY_TOKEN_CACHE_NAME = "CAGatewayToken"; public static final String SESSION_MANAGER_GROUPNAME = "RMIInfo"; public static final String SESSION_MANAGER_CACHETYPE = "cacheType"; @@ -193,6 +195,14 @@ public abstract class SessionManager implements Lifecycle { public abstract void putLogin(String key, SessionVO value); public abstract void removeLogin(String key); + + //CA Token Cache + public abstract BearerTokenInfo getCAToken(String key); + + public abstract void putCAToken(String key, BearerTokenInfo value); + + public abstract void removeCAToken(String key); + // HTTP Cache public abstract SessionVO getHttpLogin(String key); diff --git a/src/main/java/com/eactive/eai/common/session/SessionManagerForEhcache.java b/src/main/java/com/eactive/eai/common/session/SessionManagerForEhcache.java index 8c876c3..e23b465 100644 --- a/src/main/java/com/eactive/eai/common/session/SessionManagerForEhcache.java +++ b/src/main/java/com/eactive/eai/common/session/SessionManagerForEhcache.java @@ -3,6 +3,7 @@ package com.eactive.eai.common.session; import java.util.Properties; import java.util.concurrent.TimeUnit; +import com.eactive.eai.authserver.service.BearerTokenInfo; import com.eactive.eai.common.ehcache.CustomRMICacheReplicatorFactory; import com.eactive.eai.common.logger.EAIDBLogControl; import com.eactive.eai.common.message.EAIMessage; @@ -921,4 +922,19 @@ public class SessionManagerForEhcache extends SessionManager { sb.append(""); return sb.toString(); } + + @Override + public BearerTokenInfo getCAToken(String key) { + throw new UnsupportedOperationException(); + } + + @Override + public void putCAToken(String key, BearerTokenInfo value) { + throw new UnsupportedOperationException(); + } + + @Override + public void removeCAToken(String key) { + throw new UnsupportedOperationException(); + } } diff --git a/src/main/java/com/eactive/eai/common/session/SessionManagerForIgnite.java b/src/main/java/com/eactive/eai/common/session/SessionManagerForIgnite.java index fa397a5..55650a4 100644 --- a/src/main/java/com/eactive/eai/common/session/SessionManagerForIgnite.java +++ b/src/main/java/com/eactive/eai/common/session/SessionManagerForIgnite.java @@ -42,6 +42,7 @@ import org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMultic import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder; import com.eactive.eai.adapter.socket2.common.Env; +import com.eactive.eai.authserver.service.BearerTokenInfo; import com.eactive.eai.common.logger.EAIDBLogControl; import com.eactive.eai.common.message.EAIMessage; import com.eactive.eai.common.property.PropManager; @@ -63,6 +64,7 @@ import ch.qos.logback.classic.Level; // 에러내용 : Failed to execute the cache operation // (all partition owners have left the grid, partition data has been lost) //------------------------------------------------------------------------------------ + public class SessionManagerForIgnite extends SessionManager { // evictMaster Instance - single socket 관련 private static IgniteCache evictMasterCache = null; @@ -72,7 +74,8 @@ public class SessionManagerForIgnite extends SessionManager { private static IgniteCache cacheTopic = null; // 비동기 거래 복원용 private static IgniteCache cacheStore = null; - + // CA Gateway Token 관리용 + private static IgniteCache cacheCAToken = null; // webSocket Login cache 정보 private static IgniteCache cacheLogin = null; // key = loginId private static IgniteCache cacheConvertUserId = null; // 단말ID 를 userID로 변경 @@ -364,6 +367,7 @@ public class SessionManagerForIgnite extends SessionManager { caches.add(initCache(config, sessionTimeout, bootstrapAsynchronously, USERID_CAHCE_NAME, 20000, false)); caches.add(initCache(config, webSocketTimeout, bootstrapAsynchronously, WEBSOCKER_CAHCE_NAME, 20000, false)); caches.add(initCache(config, sessionTimeout, bootstrapAsynchronously, TERMINAL_CAHCE_NAME, 20000, false)); + caches.add(initCache(config, 0, bootstrapAsynchronously, CAGATEWAY_TOKEN_CACHE_NAME, 1000, false)); config.setCacheConfiguration(caches.stream().toArray(CacheConfiguration[]::new)); @@ -391,6 +395,7 @@ public class SessionManagerForIgnite extends SessionManager { cacheSocket = manager.cache(ADAPTER_CAHCE_NAME); cacheTopic = manager.cache(TOPIC_CAHCE_NAME); cacheStore = manager.cache(STORE_CAHCE_NAME); + cacheCAToken = manager.cache(CAGATEWAY_TOKEN_CACHE_NAME); cacheLogin = manager.cache(LOGIN_CAHCE_NAME); httpLogin = manager.cache(HTTP_CAHCE_NAME); @@ -810,4 +815,33 @@ public class SessionManagerForIgnite extends SessionManager { sb.append(""); return sb.toString(); } + + @Override + public BearerTokenInfo getCAToken(String key) { + try { + return cacheCAToken.get(key); + } catch (Exception e) { + logger.error("getCAToken null key=" + key, e); + return null; + } + } + + @Override + public void putCAToken(String key, BearerTokenInfo value) { + if (logger.isWarn()) { + logger.warn("Put CAToken key - " + key + ", CAToken - " + value.toString()); + } + cacheCAToken.put(key, value); + + } + + @Override + public void removeCAToken(String key) { + if (logger.isWarn()) { + logger.warn("Remove CAToken key - " + key); + } + cacheCAToken.remove(key); + + } + }