init
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
package com.openbanking.eai.agent.token;
|
||||
|
||||
import com.eactive.eai.agent.command.Command;
|
||||
import com.eactive.eai.agent.command.CommandException;
|
||||
import com.eactive.eai.common.util.Logger;
|
||||
import com.openbanking.eai.common.token.AccessTokenManager;
|
||||
import com.openbanking.eai.common.token.AccessTokenVO;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class ReloadAccessTokenCommand extends Command
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 1. 기능 : ReloadAccessTokenCommand 생성자
|
||||
* 2. 처리 개요 :
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @param
|
||||
* @return
|
||||
* @exception
|
||||
**/
|
||||
public ReloadAccessTokenCommand() {
|
||||
super("ReloadAccessTokenCommand");
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 기능 : AccessTokenManager의 데이터를 동기화
|
||||
* 2. 처리 개요 : AccessTokenManager의 데이터를 동기화
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @param
|
||||
* @return
|
||||
* @exception CommandException
|
||||
**/
|
||||
public Object execute() throws CommandException
|
||||
{
|
||||
Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
|
||||
if (logger.isInfo()) logger.info(this.name + " is executed");
|
||||
|
||||
// if ( !(args instanceof HashMap) ) {
|
||||
// String rspErrorCode = "EAIINIT001";
|
||||
// String msg = makeException(rspErrorCode, null);
|
||||
// if (logger.isError()) logger.error(msg);
|
||||
// throw new CommandException(msg);
|
||||
// }
|
||||
|
||||
try {
|
||||
// if (args == null) {
|
||||
// if (logger.isError())
|
||||
// logger.error("Refresh 토큰 정보가 없습니다.");
|
||||
// }
|
||||
|
||||
AccessTokenManager manager = AccessTokenManager.getInstance();
|
||||
String adapterGroupNameList = manager.getTargetAdapterGroup();
|
||||
String[] adapterGroupNames = adapterGroupNameList.split("[,]");
|
||||
|
||||
HashMap<String, AccessTokenVO> tokens = manager.getAllAccessTokenVO();
|
||||
|
||||
// 토큰맵에서 어댑터그룹명이 없으면 삭제로 간주
|
||||
if (tokens != null) {
|
||||
for (String key : tokens.keySet()) {
|
||||
boolean isDelete = true;
|
||||
|
||||
if (adapterGroupNames != null && adapterGroupNames.length > 0) {
|
||||
for (String adapterGroupName : adapterGroupNames) {
|
||||
if (key.equals(adapterGroupName)) {
|
||||
isDelete = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isDelete) {
|
||||
manager.stopToken(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (adapterGroupNames != null && adapterGroupNames.length > 0) {
|
||||
for (String adapterGroupName : adapterGroupNames) {
|
||||
// 어댑터그룹명이 토큰맵에 없는 경우
|
||||
if (!tokens.containsKey(adapterGroupName)) {
|
||||
// 추가로 간주 토큰 발급 시작
|
||||
manager.startToken(adapterGroupName);
|
||||
// 어댑터그룹명이 토큰맵에 있는 경우
|
||||
} else {
|
||||
// AdapterGroupVO gvo = AdapterManager.getInstance().getAdapterGroupVO(adapterGroupName);
|
||||
//
|
||||
// // 어댑터가 사용중이 아니면 중지
|
||||
// if (!gvo.isUsedFlag()) {
|
||||
// manager.stopToken(adapterGroupName);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tokens = manager.getAllAccessTokenVO();
|
||||
|
||||
if (logger.isInfo())
|
||||
logger.info(this.name + "] tokens : " + tokens);
|
||||
|
||||
if(logger.isInfo())
|
||||
logger.info(this.name + "] 토큰 정보가 Refresh 되었습니다.");
|
||||
} catch (Exception e) {
|
||||
String rspErrorCode = "EAIINIT003";
|
||||
String msg = makeException(rspErrorCode, e);
|
||||
if (logger.isError()) logger.error(msg, e);
|
||||
throw new CommandException(msg);
|
||||
}
|
||||
return "success";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,568 @@
|
||||
package com.openbanking.eai.common.token;
|
||||
|
||||
import com.eactive.eai.adapter.AdapterGroupVO;
|
||||
import com.eactive.eai.adapter.AdapterManager;
|
||||
import com.eactive.eai.adapter.AdapterPropManager;
|
||||
import com.eactive.eai.adapter.AdapterVO;
|
||||
import com.eactive.eai.agent.AgentUtil;
|
||||
import com.eactive.eai.agent.command.Command;
|
||||
import com.eactive.eai.common.exception.ExceptionUtil;
|
||||
import com.eactive.eai.common.lifecycle.Lifecycle;
|
||||
import com.eactive.eai.common.lifecycle.LifecycleException;
|
||||
import com.eactive.eai.common.lifecycle.LifecycleListener;
|
||||
import com.eactive.eai.common.lifecycle.LifecycleSupport;
|
||||
import com.eactive.eai.common.property.PropGroupVO;
|
||||
import com.eactive.eai.common.property.PropManager;
|
||||
import com.eactive.eai.common.util.Logger;
|
||||
import com.openbanking.eai.agent.token.ReloadAccessTokenCommand;
|
||||
import com.openbanking.eai.common.token.client.HttpClientAccessTokenService;
|
||||
import com.openbanking.eai.common.token.client.HttpClientAccessTokenServiceFactory;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JSONValue;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* 1. 기능 : Access 토큰 정보를 DB로 부터 로딩하고 만료시 재발급 정보를 메모리에 관리하는 Manager 클래스
|
||||
* 2. 처리 개요 : DB 프로퍼티 정보에 저장된 Access 토큰 정보를 메모리에 로딩하거나 재발급 관리한다.
|
||||
* * -
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @author :
|
||||
* @version : v 1.0.0
|
||||
* @see : 관련 기능을 참조
|
||||
* @since :
|
||||
* :
|
||||
*/
|
||||
public class AccessTokenManager implements Lifecycle
|
||||
{
|
||||
/**
|
||||
* Default Logger
|
||||
*/
|
||||
static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
|
||||
|
||||
/**
|
||||
* AccessTokenManager Single Instance
|
||||
*/
|
||||
private static AccessTokenManager instance = new AccessTokenManager();;
|
||||
|
||||
/**
|
||||
* LifecyleSupport object
|
||||
*/
|
||||
private LifecycleSupport lifecycle = new LifecycleSupport(this);
|
||||
|
||||
/**
|
||||
* 기동 여부
|
||||
*/
|
||||
private boolean started;
|
||||
|
||||
/**
|
||||
* 토큰 정보를 저장하는 collection
|
||||
*/
|
||||
private HashMap<String, AccessTokenVO> tokens;
|
||||
|
||||
/**
|
||||
* 토큰 발급 Thread를 관리하는 collection
|
||||
*/
|
||||
private HashMap<String, Thread> threads;
|
||||
|
||||
|
||||
/**
|
||||
* 1. 기능 : Default Constructor
|
||||
* 2. 처리 개요 :
|
||||
* -
|
||||
* 3. 주의사항
|
||||
*
|
||||
**/
|
||||
private AccessTokenManager() {
|
||||
tokens = new HashMap<String, AccessTokenVO>();
|
||||
threads = new HashMap<String, Thread>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 기능 : AccessTokenManager Singleton Object를 반환하는 getter method
|
||||
* 2. 처리 개요 : AccessTokenManager Singleton Object를 반환한다.
|
||||
* -
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @param
|
||||
* @return
|
||||
* @exception
|
||||
**/
|
||||
public static AccessTokenManager getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 기능 : AccessTokenManager의 초기화 여부를 반환하는 getter 메서드
|
||||
* 2. 처리 개요 : AccessTokenManager의 초기화 여부를 반환한다.
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @return 초기화 여부
|
||||
**/
|
||||
public boolean isStarted() {
|
||||
return this.started;
|
||||
}
|
||||
|
||||
// =================================================================================
|
||||
// 이 부분은 Lifecycle용으로 제공되는 메소드이다.
|
||||
/**
|
||||
* 1. 기능 : Lifecycle의 start 메서드로 AccessTokenManager를 초기화하는 메서드
|
||||
* 2. 처리 개요 : PropertyDAO를 이용해 추출 Rule 정보 모두를 가져와 초기화한다. <---
|
||||
* -
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @param
|
||||
* @return
|
||||
* @exception
|
||||
**/
|
||||
public void start() throws LifecycleException {
|
||||
if (started)
|
||||
throw new LifecycleException("RECEAICPM201");
|
||||
|
||||
// Notify our interested LifecycleListeners
|
||||
lifecycle.fireLifecycleEvent(STARTING_EVENT, this);
|
||||
|
||||
try {
|
||||
// accessToken 초기화
|
||||
tokens.clear();
|
||||
|
||||
init();
|
||||
} catch(Exception e) {
|
||||
throw new LifecycleException(ExceptionUtil.getErrorCode(e,"RECEAICPM201"));
|
||||
}
|
||||
|
||||
started = true;
|
||||
if (logger.isWarn()){
|
||||
logger.warn("AccessTokenManager] It is started.");
|
||||
}
|
||||
// Notify our interested LifecycleListeners
|
||||
lifecycle.fireLifecycleEvent(STARTED_EVENT, this);
|
||||
}
|
||||
|
||||
private void init() throws Exception {
|
||||
|
||||
String adapterGroupNameList = getTargetAdapterGroup();
|
||||
String[] adapterGroupNames = adapterGroupNameList.split("[,]");
|
||||
|
||||
if (adapterGroupNames.length > 0) {
|
||||
// 어댑터그룹별 토큰 관리
|
||||
for (String adapterGroupName : adapterGroupNames) {
|
||||
startToken(adapterGroupName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 기능 : Lifecycle의 stop 메서드로 AccessTokenManager를 종료하는 메서드
|
||||
* 2. 처리 개요 : 멤버에 캐싱한 Access 토큰 정보를 clear한다.
|
||||
* -
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @param
|
||||
* @return
|
||||
* @exception
|
||||
**/
|
||||
public void stop() throws LifecycleException {
|
||||
// Validate and update our current component state
|
||||
if (!started)
|
||||
throw new LifecycleException("RECEAICPM203");
|
||||
|
||||
// Notify our interested LifecycleListeners
|
||||
lifecycle.fireLifecycleEvent(STOPING_EVENT, this);
|
||||
|
||||
// 기동중인 Thread가 존재하면 전체를 중지 시킨다.
|
||||
if (threads.size() > 0) {
|
||||
threads.forEach((n, t) ->
|
||||
{
|
||||
try {
|
||||
if (t.isAlive()) {
|
||||
t.stop();
|
||||
|
||||
logger.warn("AccessTokenManager] STOP (" + n + ") stopped.");
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
this.tokens = null;
|
||||
|
||||
started = false;
|
||||
if (logger.isWarn()){
|
||||
logger.warn("AccessTokenManager] It is stopped.");
|
||||
}
|
||||
// Notify our interested LifecycleListeners
|
||||
lifecycle.fireLifecycleEvent(STOPPED_EVENT, this);
|
||||
}
|
||||
|
||||
public void startToken(String adapterGroupName) {
|
||||
|
||||
// 이미 기동중인 Thread가 존재하면 Skip한다.
|
||||
if (threads.containsKey(adapterGroupName)) {
|
||||
logger.warn("AccessTokenManager] SKIP (" + adapterGroupName + ") thread aleady started");
|
||||
return;
|
||||
}
|
||||
|
||||
Runnable runnable = new Runnable() {
|
||||
long sleepTime = 60;
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
public void run() {
|
||||
while(true) {
|
||||
long interval = 24 * 60 * 60;
|
||||
AdapterGroupVO gvo = AdapterManager.getInstance().getAdapterGroupVO(adapterGroupName);
|
||||
// 어댑터가 사용중이 아니면 Skip한다.
|
||||
if (gvo != null && gvo.isUsedFlag()) {
|
||||
try {
|
||||
PropGroupVO vo = PropManager.getInstance().getPropGroupVO(AccessTokenVO.PROP_GROUP);
|
||||
String tokenInfo = vo.getProperty(adapterGroupName);
|
||||
|
||||
// 토큰 정보가 없을 경우 중지한다.
|
||||
if (StringUtils.isBlank(tokenInfo)) {
|
||||
logger.error("AccessTokenManager] INFO (" + adapterGroupName + ") is NULL");
|
||||
break;
|
||||
}
|
||||
|
||||
JSONObject tokenInfoObject = (JSONObject) JSONValue.parse(tokenInfo);
|
||||
// 초단위 입력. 값이 없을 경우 1일(24 * 60 * 60초)
|
||||
try {
|
||||
interval = tokenInfoObject.containsKey("interval") ? Long.parseLong((String) tokenInfoObject.get("interval")) : 24 * 60 * 60;
|
||||
} catch(Exception e) {
|
||||
logger.warn("AccessTokenManager] SLEEP (" + adapterGroupName + ") default interval");
|
||||
}
|
||||
|
||||
long intervalTime = startTime + (interval * 1000L);
|
||||
|
||||
// interval이 0보다 작은 경우 Thread를 중지한다.
|
||||
if (interval < 0) {
|
||||
logger.error("AccessTokenManager] STOP (" + adapterGroupName + ")");
|
||||
break;
|
||||
}
|
||||
|
||||
// 해당 어댑터그룹명의 토큰이 존재할 경우
|
||||
if (!tokens.isEmpty() && tokens.containsKey(adapterGroupName)) {
|
||||
if (System.currentTimeMillis() > intervalTime) {
|
||||
long tempTime = System.currentTimeMillis();
|
||||
AccessTokenVO accessToken = tokens.get(adapterGroupName);
|
||||
|
||||
// 다음 스케줄 시간 전까지 만료가 될경우 재 발급
|
||||
if (accessToken.getExpiration() != null && accessToken.getExpiration().before(new Date(intervalTime))) {
|
||||
refresh(adapterGroupName, true);
|
||||
|
||||
logger.warn("AccessTokenManager] REFRESH (" + adapterGroupName + ") AccessToken : " + instance.getAccessTokenVO(adapterGroupName));
|
||||
} else {
|
||||
logger.info("AccessTokenManager] SKIP (" + adapterGroupName + ") AccessToken : " + instance.getAccessTokenVO(adapterGroupName));
|
||||
}
|
||||
|
||||
startTime = tempTime;
|
||||
}
|
||||
// 해당 어댑터그룹명의 토큰이 존재하지 않을 경우
|
||||
} else {
|
||||
long tempTime = System.currentTimeMillis();
|
||||
|
||||
refresh(adapterGroupName);
|
||||
|
||||
startTime = tempTime;
|
||||
|
||||
logger.warn("AccessTokenManager] NEW (" + adapterGroupName + ") AccessToken : " + instance.getAccessTokenVO(adapterGroupName));
|
||||
}
|
||||
} catch(Throwable t) {
|
||||
logger.error("AccessTokenManager] FAIL (" + adapterGroupName + ") start failed", t);
|
||||
}
|
||||
} else {
|
||||
logger.info("AccessTokenManager] SKIP (" + adapterGroupName + ") adapter not used");
|
||||
}
|
||||
|
||||
try {
|
||||
logger.info("AccessTokenManager] SLEEP (" + adapterGroupName + ") " + sleepTime + " sec.");
|
||||
|
||||
Thread.sleep(sleepTime * 1000L);
|
||||
} catch(InterruptedException e) {
|
||||
logger.error("AccessTokenManager] SLEEP (" + adapterGroupName + ") failed", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Thread thread = new Thread(runnable);
|
||||
thread.setName(adapterGroupName + "-AccessTokenRefresh");
|
||||
thread.setPriority(Thread.MAX_PRIORITY);
|
||||
thread.start();
|
||||
|
||||
// Thread 관리를 위함
|
||||
threads.put(adapterGroupName, thread);
|
||||
}
|
||||
|
||||
public void stopToken(String adapterGroupName) {
|
||||
|
||||
// 기동중인 Thread가 존재하지 않으면 Skip한다.
|
||||
if (!threads.containsKey(adapterGroupName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Thread t = threads.get(adapterGroupName);
|
||||
|
||||
if (t.isAlive()) {
|
||||
t.stop();
|
||||
|
||||
if (logger.isDebugEnabled()){
|
||||
logger.warn("AccessTokenManager] STOP (" + adapterGroupName + ") stopped.");
|
||||
}
|
||||
|
||||
threads.remove(adapterGroupName);
|
||||
tokens.remove(adapterGroupName);
|
||||
}
|
||||
}
|
||||
|
||||
public String getStatus(String adapterGroupName) {
|
||||
|
||||
if (!threads.containsKey(adapterGroupName)) {
|
||||
return "STOPED";
|
||||
} else {
|
||||
return "STARTED";
|
||||
|
||||
// Thread t = threads.get(adapterGroupName);
|
||||
//
|
||||
// if (t.isAlive()) {
|
||||
// return "STARTED";
|
||||
// } else {
|
||||
// return "SLEEP";
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 기능 : LifecycleListener를 등록하는 메서드
|
||||
* 2. 처리 개요 : LifecycleListener를 등록한다.
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @param listener LifecycleEvent를 수신한 LifecycleListener
|
||||
**/
|
||||
public void addLifecycleListener(LifecycleListener listener)
|
||||
{
|
||||
lifecycle.addLifecycleListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 기능 : 등록된 LifecycleListener 리스트를 반환하는 메서드
|
||||
* 2. 처리 개요 : 등록된 LifecycleListener 리스트를 반환하다.
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @return 등록된 LifecycleListener 리스트
|
||||
**/
|
||||
public LifecycleListener[] findLifecycleListeners()
|
||||
{
|
||||
return lifecycle.findLifecycleListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 기능 : 등록된 LifecycleListener를 삭제하는 메서드
|
||||
* 2. 처리 개요 : 파라미터의 LifecycleListener를 삭제한다.
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @param listener 삭제할 LifecycleListener
|
||||
**/
|
||||
public void removeLifecycleListener(LifecycleListener listener)
|
||||
{
|
||||
lifecycle.removeLifecycleListener(listener);
|
||||
}
|
||||
|
||||
public String getTargetAdapterGroup() throws Exception {
|
||||
|
||||
PropGroupVO vo = PropManager.getInstance().getPropGroupVO(AccessTokenVO.PROP_GROUP);
|
||||
return vo.getProperty(AccessTokenVO.TARGET_ADAPTER_GROUP);
|
||||
}
|
||||
|
||||
|
||||
public void refresh() throws Exception {
|
||||
if(logger.isWarn()) {
|
||||
logger.warn("AccessTokenManager] refresh all Started ...");
|
||||
}
|
||||
String adapterGroupNameList = getTargetAdapterGroup();
|
||||
String[] adapterGroupNames = adapterGroupNameList.split("[,]");
|
||||
|
||||
if (adapterGroupNames.length > 0) {
|
||||
// 어댑터별 토큰 관리
|
||||
for (String adapterGroupName : adapterGroupNames) {
|
||||
refresh(adapterGroupName);
|
||||
}
|
||||
}
|
||||
|
||||
if(logger.isWarn()) {
|
||||
logger.warn("AccessTokenManager] refresh all finished ...");
|
||||
}
|
||||
}
|
||||
|
||||
public void refresh(String adapterGroupName) throws Exception {
|
||||
refresh(adapterGroupName, false);
|
||||
}
|
||||
|
||||
public synchronized void refresh(String adapterGroupName, boolean isRefresh) throws Exception {
|
||||
boolean isExpired = true;
|
||||
|
||||
if (tokens.containsKey(adapterGroupName)) {
|
||||
AccessTokenVO accessToken = tokens.get(adapterGroupName);
|
||||
isExpired = accessToken.isExpired();
|
||||
}
|
||||
|
||||
// 만료됐거나 토큰 존재하지 않을때
|
||||
if (isExpired || isRefresh) {
|
||||
// 기존 토큰이 있을 경우 제거
|
||||
tokens.remove(adapterGroupName);
|
||||
|
||||
AdapterGroupVO gvo = AdapterManager.getInstance().getAdapterGroupVO(adapterGroupName);
|
||||
|
||||
if (gvo != null && gvo.getAdapters().hasNext()) {
|
||||
// 어댑터의 첫 프로퍼티 정보를 참조
|
||||
AdapterVO avo = (AdapterVO)gvo.getAdapters().next();
|
||||
|
||||
Properties properties = AdapterPropManager.getInstance().getProperties(avo.getPropGroupName());
|
||||
|
||||
String type = properties.getProperty("ADAPTER_TOKEN_ISSUING_CLIENT_TYPE");
|
||||
|
||||
// 토큰 발급 서비스가 다를 경우 HttpClientTokenService 인터페이스를 구현한 서비스를 추가
|
||||
HttpClientAccessTokenService service = HttpClientAccessTokenServiceFactory.createFactory(type);
|
||||
if(service != null) {
|
||||
AccessTokenVO accessToken = (AccessTokenVO) service.execute(adapterGroupName, properties);
|
||||
this.tokens.put(adapterGroupName, accessToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 기능 : 모든 Access 토큰을 찾아 반환하는 메서드
|
||||
* 2. 처리 개요 : 모든 Access 토큰을 찾아 HashMap 객체로반환한다.
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @return Access 토큰 정보 VO 객체 Collection
|
||||
**/
|
||||
public HashMap<String, AccessTokenVO> getAllAccessTokenVO() {
|
||||
return tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 기능 : Access 토큰 정보를 반환하는 메서드
|
||||
* 2. 처리 개요 : Access 토큰 정보를 반환한다.
|
||||
* -
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @return Access 토큰 정보
|
||||
**/
|
||||
public AccessTokenVO getAccessTokenVO(String adapterGroupName) {
|
||||
AccessTokenVO accessToken = null;
|
||||
|
||||
try {
|
||||
accessToken = tokens.get(adapterGroupName);
|
||||
} catch(Exception e) {
|
||||
if (logger.isError()) logger.error("토큰을 찾을 수 없습니다. ["+adapterGroupName+"] ", e);
|
||||
}
|
||||
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 기능 : Access 토큰 값를 반환하는 메서드
|
||||
* 2. 처리 개요 : Access 토큰 값를 반환한다.
|
||||
* -
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @return accessToken 값
|
||||
**/
|
||||
public String getAccessToken(String adapterGroupName) {
|
||||
String accessToken = null;
|
||||
|
||||
try {
|
||||
accessToken = tokens.get(adapterGroupName).getAccessToken();
|
||||
} catch(Exception e) {
|
||||
if (logger.isError()) logger.error("토큰을 찾을 수 없습니다. ["+adapterGroupName+"] ", e);
|
||||
}
|
||||
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 기능 : Access 토큰 정보를 등록하는 메서드
|
||||
* 2. 처리 개요 : Access 토큰 정보를 등록한다.
|
||||
* -
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @param vo AccessTokenVO
|
||||
**/
|
||||
public void setAllAccessTokenVO(HashMap<String, AccessTokenVO> tokens) {
|
||||
this.tokens = tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 기능 : Access 토큰 정보를 등록하는 메서드
|
||||
* 2. 처리 개요 : Access 토큰 정보를 등록한다.
|
||||
* -
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @param vo AccessTokenVO
|
||||
**/
|
||||
public void setAccessTokenVO(String adapterGroupName, AccessTokenVO accessToken) {
|
||||
tokens.put(adapterGroupName, accessToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 기능 : Access 토큰를 삭제하는 메서드
|
||||
* 2. 처리 개요 : Access 토큰를 삭제한다.
|
||||
* -
|
||||
* 3. 주의사항
|
||||
*
|
||||
**/
|
||||
public void removeAccessTokenVO(String adapterGroupName) {
|
||||
tokens.remove(adapterGroupName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 기능 : Access 토큰를 재발급하는 메서드
|
||||
* 2. 처리 개요 : Access 토큰를 재발급한다.
|
||||
* -
|
||||
* 3. 주의사항
|
||||
*
|
||||
**/
|
||||
public synchronized AccessTokenVO retryAccessTokenVO(String adapterGroupName, Properties properties, String oldToken) throws Exception {
|
||||
|
||||
AccessTokenVO accessToken = getAccessTokenVO(adapterGroupName);
|
||||
|
||||
// 동시 요청이 발생할 경우 synchronized 처리를 했기때문에 토큰을 다시 한번 체크한다.
|
||||
if (accessToken == null || accessToken.isExpired()
|
||||
|| StringUtils.equals(accessToken.getAccessToken(), oldToken)) {
|
||||
String type = properties.getProperty("ADAPTER_TOKEN_ISSUING_CLIENT_TYPE");
|
||||
|
||||
HttpClientAccessTokenService service = HttpClientAccessTokenServiceFactory.createFactory(type);
|
||||
if(service != null) {
|
||||
accessToken = (AccessTokenVO) service.execute(adapterGroupName, properties);
|
||||
}
|
||||
tokens.put(adapterGroupName, accessToken);
|
||||
}
|
||||
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. 기능 : Access 토큰를 동기화하는 메서드
|
||||
* 2. 처리 개요 : Access 토큰를 동기화한다.
|
||||
* -
|
||||
* 3. 주의사항
|
||||
* @throws Exception
|
||||
*
|
||||
**/
|
||||
public synchronized void notifyAllAccessTokenVO() throws Exception {
|
||||
try {
|
||||
Command command = new ReloadAccessTokenCommand();
|
||||
command.setArgs(tokens);
|
||||
AgentUtil.broadcast(command);
|
||||
} catch (Exception e) {
|
||||
throw new Exception("토큰 동기화에 실패했습니다. " +e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.openbanking.eai.common.token;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public interface AccessTokenVO
|
||||
{
|
||||
public static final String BEARER_TYPE = "Bearer";
|
||||
|
||||
public static final String PROP_GROUP = "OAuthInfo";
|
||||
public static final String HEADER_CONTENT_TYPE = "header.content.type";
|
||||
public static final String TARGET_ADAPTER_GROUP = "target.adapter.group";
|
||||
|
||||
// public static final String OAUTH_ACCESS_TOKEN_URI = "oauth.token.uri";
|
||||
// public static final String OAUTH_CLIENT_ID = "oauth.client.id";
|
||||
// public static final String OAUTH_CLIENT_SECRET = "oauth.client.secret";
|
||||
// public static final String OAUTH_SCOPE = "oauth.scope";
|
||||
// public static final String OAUTH_GRANT_TYPE = "oauth.grant.type";
|
||||
|
||||
public abstract String getAccessToken();
|
||||
|
||||
public abstract Date getExpiration();
|
||||
|
||||
public abstract boolean isExpired();
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.openbanking.eai.common.token;
|
||||
|
||||
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 1. 기능 : OAuth2 토큰 정보를 표현하는 Java Value Object 클래스.
|
||||
* 2. 처리 개요 : OAuth2 토큰 정보를 정의한다.
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @author :
|
||||
* @version : v 1.0.0
|
||||
* @see : 관련 기능을 참조
|
||||
* @since :
|
||||
* :
|
||||
*/
|
||||
public class OAuth2AccessTokenVO implements AccessTokenVO, Serializable
|
||||
{
|
||||
private String accessToken;
|
||||
private String tokenType;
|
||||
private Date expiration;
|
||||
private String scope;
|
||||
private String clientUseCode;
|
||||
|
||||
public OAuth2AccessTokenVO() {
|
||||
|
||||
}
|
||||
|
||||
public OAuth2AccessTokenVO(OAuth2AccessTokenVO oAuth2AccessTokenVO) {
|
||||
this.accessToken = oAuth2AccessTokenVO.getAccessToken();
|
||||
this.tokenType = oAuth2AccessTokenVO.getTokenType();
|
||||
this.expiration = oAuth2AccessTokenVO.getExpiration();
|
||||
this.scope = oAuth2AccessTokenVO.getScope();
|
||||
this.clientUseCode = oAuth2AccessTokenVO.getClientUseCode();
|
||||
}
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public void setAccessToken(String accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
public String getAuthorization() {
|
||||
return String.format("%s %s", BEARER_TYPE, accessToken);
|
||||
}
|
||||
|
||||
public String getTokenType() {
|
||||
return tokenType;
|
||||
}
|
||||
|
||||
public void setTokenType(String tokenType) {
|
||||
this.tokenType = tokenType;
|
||||
}
|
||||
|
||||
public long getExpiresIn() {
|
||||
return expiration == null ? 0 : Long.valueOf((expiration.getTime() - System.currentTimeMillis()) / 1000L);
|
||||
}
|
||||
|
||||
public void setExpiresIn(long expiresIn) {
|
||||
setExpiration(new Date(System.currentTimeMillis() + (expiresIn * 1000L)));
|
||||
}
|
||||
|
||||
public Date getExpiration() {
|
||||
return expiration;
|
||||
}
|
||||
|
||||
public void setExpiration(Date expiration) {
|
||||
this.expiration = expiration;
|
||||
}
|
||||
|
||||
public boolean isExpired() {
|
||||
return expiration != null && expiration.before(new Date());
|
||||
}
|
||||
|
||||
public String getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public void setScope(String scope) {
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
public String getClientUseCode() {
|
||||
return clientUseCode;
|
||||
}
|
||||
|
||||
public void setClientUseCode(String clientUseCode) {
|
||||
this.clientUseCode = clientUseCode;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return ReflectionToStringBuilder.toString(this, ToStringStyle.DEFAULT_STYLE);
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
|
||||
package com.openbanking.eai.common.token.client;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
|
||||
/**
|
||||
* 1. 기능 : HTTP 웹 컴포넌트를 GET/POST 방식으로 호출할 수 있는 기능을 제공한다.
|
||||
* 2. 처리 개요 :
|
||||
* * - 2009.11.24 retry 로직 제거 : 요청
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @author :
|
||||
* @version : v 1.0.0
|
||||
* @see : WLIAdapterFactory.java, WLIAdapter.java, WLIDefaultAdapter.java
|
||||
* @since :
|
||||
|
||||
*/
|
||||
public interface HttpClientAccessTokenService {
|
||||
|
||||
/**
|
||||
* 1. 기능 : 토큰발급 처리에 사용한다.
|
||||
* 2. 처리 개요 :
|
||||
* - 속성 정보를 설정 하고 토큰 발급 URL 호출 한다.
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @param prop Http Adapter 속성 정보
|
||||
* @return 반환 된 AccessTokenVO
|
||||
* @exception Exception 수동 시스템 간 통신 중 발생
|
||||
**/
|
||||
public Object execute(String name, Properties prop) throws Exception ;
|
||||
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package com.openbanking.eai.common.token.client;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.eactive.eai.common.util.Logger;
|
||||
|
||||
public class HttpClientAccessTokenServiceFactory {
|
||||
static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER);
|
||||
static private ConcurrentHashMap<String, HttpClientAccessTokenService> h = new ConcurrentHashMap<String, HttpClientAccessTokenService>();
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public HttpClientAccessTokenServiceFactory() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* 공통코드 HTTP_CLIENT_TOKEN_ISSUANCE_CLASS 에 정의된 구현체를 생성 한다.
|
||||
*
|
||||
* @param className
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static HttpClientAccessTokenService createFactory(String className) {
|
||||
if (h.containsKey(className)) {
|
||||
return (HttpClientAccessTokenService) h.get(className);
|
||||
}
|
||||
|
||||
HttpClientAccessTokenService service = null;
|
||||
try {
|
||||
Class cl = Class.forName(className);
|
||||
service = (HttpClientAccessTokenService) cl.newInstance();
|
||||
if (service != null) {
|
||||
h.put(className, service);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Cannot create a HttpClientAccessTokenService. - {}", className);
|
||||
}
|
||||
|
||||
return service;
|
||||
}
|
||||
}
|
||||
+184
@@ -0,0 +1,184 @@
|
||||
|
||||
package com.openbanking.eai.common.token.client.impl;
|
||||
|
||||
import com.eactive.eai.adapter.http.secure.CustomHttpsSocketFactory;
|
||||
import com.eactive.eai.adapter.http.secure.EasySSLProtocolSocketFactory;
|
||||
import com.eactive.eai.common.property.PropManager;
|
||||
import com.eactive.eai.common.util.Logger;
|
||||
import com.eactive.eai.common.util.ScpDbAgentUtil;
|
||||
import com.openbanking.eai.common.token.AccessTokenVO;
|
||||
import com.openbanking.eai.common.token.OAuth2AccessTokenVO;
|
||||
import com.openbanking.eai.common.token.client.HttpClientAccessTokenService;
|
||||
import org.apache.commons.httpclient.HttpClient;
|
||||
import org.apache.commons.httpclient.HttpVersion;
|
||||
import org.apache.commons.httpclient.methods.PostMethod;
|
||||
import org.apache.commons.httpclient.protocol.Protocol;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JSONValue;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.Date;
|
||||
import java.util.Properties;
|
||||
|
||||
|
||||
/**
|
||||
* 1. 기능 : CODEF API 시스템을 통해 토큰 발급 수행
|
||||
* 2. 처리 개요 :
|
||||
* * - 2020.09.04 - 속성 정보를 설정 하고 토큰 발급 URL 호출 한다.
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @author :
|
||||
* @version : v 1.0.0
|
||||
* @see : HttpClientAccessTokenServiceFactory
|
||||
* @since :
|
||||
|
||||
*/
|
||||
public class HttpClientAccessTokenServiceForCODEF implements HttpClientAccessTokenService {
|
||||
public static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
|
||||
|
||||
public static final String OAUTH_ACCESS_TOKEN_URI = "url";
|
||||
public static final String OAUTH_CLIENT_ID = "client_id";
|
||||
public static final String OAUTH_CLIENT_SECRET = "client_secret";
|
||||
public static final String OAUTH_SCOPE = "scope";
|
||||
public static final String OAUTH_GRANT_TYPE = "grant_type";
|
||||
|
||||
public static final String TOKEN_ERROR_CHECK_KEY = "token_error_check_key";
|
||||
public static final String TOKEN_ERROR_CHECK_VALUES = "token_error_check_values";
|
||||
|
||||
public AccessTokenVO execute(String name, Properties prop) throws Exception {
|
||||
String url = prop.getProperty("URL");
|
||||
String encode = prop.getProperty("ENCODE");
|
||||
String timeoutTemp = prop.getProperty("HTTP_TIME_OUT", "0");
|
||||
String connectionTimeoutTemp = prop.getProperty("CONNECTION_TIMEOUT", "0");
|
||||
|
||||
int timeout = Integer.parseInt(timeoutTemp);
|
||||
int connectionTimeout = Integer.parseInt(connectionTimeoutTemp);
|
||||
long currentTime = System.currentTimeMillis();
|
||||
|
||||
PropManager propManager = PropManager.getInstance();
|
||||
String tokenInfo = propManager.getProperty(AccessTokenVO.PROP_GROUP, name);
|
||||
|
||||
if (StringUtils.isBlank(tokenInfo)) {
|
||||
throw new Exception("TokenInfo is NULL");
|
||||
}
|
||||
|
||||
/**
|
||||
* 프로퍼티 OAuthInfo에 프로퍼티 명이 TokenManager에서 관리하는 Key(어댑터그룹명)로 등록
|
||||
* interval, url, client_id, client_secret(암호화), scope, grant_type
|
||||
*
|
||||
* ex) _TST_OU_RST_SyC =>
|
||||
* {
|
||||
* "interval": "86400",
|
||||
* "url": "oauth/2.0/token",
|
||||
* "client_id": "l7xx3b02c23ae8d64d2fb12a7266895f8687",
|
||||
* "client_secret": "4e88d1d2edb44eadb35a1f6da9823a64",
|
||||
* "scope": "read",
|
||||
* "grant_type": "client_credentials"
|
||||
* }
|
||||
*/
|
||||
JSONObject tokenInfoObject = (JSONObject) JSONValue.parse(tokenInfo);
|
||||
|
||||
String oauthAccessTokenUrl = tokenInfoObject.containsKey(OAUTH_ACCESS_TOKEN_URI) ? (String)tokenInfoObject.get(OAUTH_ACCESS_TOKEN_URI) : "";
|
||||
String oauthClientId = tokenInfoObject.containsKey(OAUTH_CLIENT_ID ) ? (String)tokenInfoObject.get(OAUTH_CLIENT_ID ) : "";
|
||||
String oauthClientSecret = tokenInfoObject.containsKey(OAUTH_CLIENT_SECRET ) ? (String)tokenInfoObject.get(OAUTH_CLIENT_SECRET ) : "";
|
||||
String oauthScope = tokenInfoObject.containsKey(OAUTH_SCOPE ) ? (String)tokenInfoObject.get(OAUTH_SCOPE ) : "";
|
||||
String oauthGrantType = tokenInfoObject.containsKey(OAUTH_GRANT_TYPE ) ? (String)tokenInfoObject.get(OAUTH_GRANT_TYPE ) : "";
|
||||
|
||||
//2020-03-12 Scp 모듈 Util로 변경
|
||||
// client_secret를 복호화한다
|
||||
try {
|
||||
oauthClientSecret = ScpDbAgentUtil.ScpDecB64(PropManager.getInstance().getProperties(ScpDbAgentUtil.EXT_MODULE), oauthClientSecret, "EUC-KR");
|
||||
} catch (Exception e) {
|
||||
logger.error("addInboundErrorInfo] scpdb_agent encryption Error - " + e.getMessage());
|
||||
}
|
||||
|
||||
String uri = "";
|
||||
if (StringUtils.contains(oauthAccessTokenUrl, "http://")
|
||||
|| StringUtils.contains(oauthAccessTokenUrl, "https://")) {
|
||||
uri = oauthAccessTokenUrl;
|
||||
} else {
|
||||
uri = url + "/" + oauthAccessTokenUrl;
|
||||
}
|
||||
|
||||
String contentType = propManager.getProperty(AccessTokenVO.PROP_GROUP, AccessTokenVO.HEADER_CONTENT_TYPE);
|
||||
|
||||
HttpClient mclient = new HttpClient();
|
||||
PostMethod httpMethod = new PostMethod(uri);
|
||||
|
||||
if(timeout > -1) {
|
||||
httpMethod.getParams().setSoTimeout(timeout);
|
||||
}
|
||||
|
||||
if ( connectionTimeout != 0) {
|
||||
httpMethod.getParams().setParameter("http.connection.timeout", connectionTimeout);
|
||||
}
|
||||
httpMethod.getParams().setParameter("http.protocol.version", HttpVersion.HTTP_1_0);
|
||||
|
||||
if(uri != null && uri.startsWith("https")){
|
||||
Protocol.registerProtocol("https", new Protocol("https",
|
||||
new CustomHttpsSocketFactory(new EasySSLProtocolSocketFactory()), 443));
|
||||
}
|
||||
|
||||
try {
|
||||
httpMethod.setParameter(OAUTH_GRANT_TYPE , oauthGrantType );
|
||||
httpMethod.setParameter(OAUTH_SCOPE , oauthScope ); ////
|
||||
|
||||
String basicAuth = oauthClientId + ":" + oauthClientSecret;
|
||||
basicAuth = "Basic " + Base64.getEncoder().encodeToString(basicAuth.getBytes());
|
||||
httpMethod.setRequestHeader("Authorization", basicAuth);
|
||||
httpMethod.setRequestHeader("Content-Type", contentType + "; charset=" + encode);
|
||||
|
||||
logger.debug("HttpClientAccessTokenServiceForCODEF] oauthClientId = ["+ oauthClientId +"]");
|
||||
logger.debug("HttpClientAccessTokenServiceForCODEF] oauthClientSecret = ["+ oauthClientSecret +"]");
|
||||
logger.debug("HttpClientAccessTokenServiceForCODEF] oauthScope = ["+ oauthScope +"]");
|
||||
logger.debug("HttpClientAccessTokenServiceForCODEF] oauthGrantType = ["+ oauthGrantType +"]");
|
||||
logger.debug("HttpClientAccessTokenServiceForCODEF] contentType = ["+ contentType +"]");
|
||||
logger.debug("HttpClientAccessTokenServiceForCODEF] encode = ["+ encode +"]");
|
||||
logger.debug("HttpClientAccessTokenServiceForCODEF] Authorization = ["+ basicAuth +"]");
|
||||
|
||||
int status = mclient.executeMethod(httpMethod);
|
||||
|
||||
if (status !=200) {
|
||||
throw new Exception ("oauth token receive status fail value= " + status);
|
||||
}
|
||||
|
||||
byte[] responseBody = httpMethod.getResponseBody();
|
||||
String responseString = new String(responseBody, encode);
|
||||
|
||||
OAuth2AccessTokenVO accessToken = new OAuth2AccessTokenVO();
|
||||
|
||||
if (StringUtils.isNotBlank(responseString)) {
|
||||
logger.debug("HttpClientAccessTokenServiceForCODEF] oauthToken RECV = ["+ responseString +"]");
|
||||
|
||||
JSONObject responseJSON = (JSONObject) JSONValue.parse(responseString);
|
||||
|
||||
if (responseJSON.containsKey("access_token")
|
||||
&& responseJSON.containsKey("token_type")
|
||||
&& responseJSON.containsKey("expires_in")
|
||||
&& responseJSON.containsKey("scope")) {
|
||||
accessToken.setAccessToken((String) responseJSON.get("access_token"));
|
||||
accessToken.setTokenType ((String) responseJSON.get("token_type" ));
|
||||
accessToken.setExpiration (new Date(currentTime + ((long) responseJSON.get("expires_in") * 1000L)));
|
||||
accessToken.setScope ((String) responseJSON.get("scope" ));
|
||||
}
|
||||
|
||||
if (responseJSON.containsKey("client_use_code")) {
|
||||
accessToken.setClientUseCode((String) responseJSON.get("client_use_code"));
|
||||
}
|
||||
|
||||
logger.debug("HttpClientAccessTokenServiceForCODEF] oauthToken ="+ accessToken.toString());
|
||||
} else {
|
||||
throw new Exception ("oauth token return null");
|
||||
}
|
||||
|
||||
return accessToken;
|
||||
// 오류 처리 상세화 필요
|
||||
} catch (Exception e) {
|
||||
logger.error("HttpClientAccessTokenServiceForCODEF] oauth token fail : " + e.toString() ,e);
|
||||
throw e;
|
||||
} finally {
|
||||
httpMethod.releaseConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
|
||||
package com.openbanking.eai.common.token.client.impl;
|
||||
|
||||
import com.eactive.eai.common.property.PropManager;
|
||||
import com.eactive.eai.common.util.Logger;
|
||||
import com.eactive.eai.common.util.ScpDbAgentUtil;
|
||||
import com.openbanking.eai.common.token.AccessTokenVO;
|
||||
import com.openbanking.eai.common.token.OAuth2AccessTokenVO;
|
||||
import com.openbanking.eai.common.token.client.HttpClientAccessTokenService;
|
||||
import org.apache.commons.httpclient.HttpClient;
|
||||
import org.apache.commons.httpclient.HttpVersion;
|
||||
import org.apache.commons.httpclient.methods.PostMethod;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JSONValue;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.Properties;
|
||||
|
||||
|
||||
/**
|
||||
* 1. 기능 : HTTP 웹 컴포넌트를 POST 방식으로 호출할 수 있는 기능을 제공한다.
|
||||
* 2. 처리 개요 :
|
||||
* * - 2009.11.24 retry 로직 제거 : 요청
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @author :
|
||||
* @version : v 1.0.0
|
||||
* @see : WLIAdapterFactory.java, WLIAdapter.java, WLIDefaultAdapter.java
|
||||
* @since :
|
||||
|
||||
*/
|
||||
public class HttpClientAccessTokenServiceForKFTC implements HttpClientAccessTokenService {
|
||||
|
||||
public static Logger logger = Logger.getLogger(Logger.LOGGER_DEFAULT);
|
||||
|
||||
public static final String OAUTH_ACCESS_TOKEN_URI = "url";
|
||||
public static final String OAUTH_CLIENT_ID = "client_id";
|
||||
public static final String OAUTH_CLIENT_SECRET = "client_secret";
|
||||
public static final String OAUTH_SCOPE = "scope";
|
||||
public static final String OAUTH_GRANT_TYPE = "grant_type";
|
||||
|
||||
/**
|
||||
* 1. 기능 : 결제원 오픈뱅킹 토큰 발급에 사용
|
||||
* 2. 처리 개요 :
|
||||
* - 속성 정보를 설정 하고 토큰 발급 URL 호출 한다.
|
||||
* 3. 주의사항
|
||||
*
|
||||
* @param prop Http Adapter 속성 정보
|
||||
* @return 반환 된 AccessTokenVO
|
||||
* @exception Exception 수동 시스템 간 통신 중 발생
|
||||
**/
|
||||
public AccessTokenVO execute(String name, Properties prop) throws Exception {
|
||||
|
||||
String url = prop.getProperty("URL");
|
||||
String encode = prop.getProperty("ENCODE");
|
||||
String timeoutTemp = prop.getProperty("HTTP_TIME_OUT", "0");
|
||||
String connectionTimeoutTemp = prop.getProperty("CONNECTION_TIMEOUT", "0");
|
||||
|
||||
// // OAuth 정보 관리 대상을 어댑터의 프로퍼티로 변경
|
||||
// String oauthAccessTokenUrl = prop.getProperty(AccessTokenVO.OAUTH_ACCESS_TOKEN_URL);
|
||||
// String oauthClientId = prop.getProperty(AccessTokenVO.OAUTH_CLIENT_ID);
|
||||
// String oauthClientSecret = prop.getProperty(AccessTokenVO.OAUTH_CLIENT_SECRET);
|
||||
// String oauthScope = prop.getProperty(AccessTokenVO.OAUTH_SCOPE);
|
||||
// String oauthGrantType = prop.getProperty(AccessTokenVO.OAUTH_GRANT_TYPE);
|
||||
|
||||
int timeout = Integer.parseInt(timeoutTemp);
|
||||
int connectionTimeout = Integer.parseInt(connectionTimeoutTemp);
|
||||
long currentTime = System.currentTimeMillis();
|
||||
|
||||
PropManager propManager = PropManager.getInstance();
|
||||
String tokenInfo = propManager.getProperty(AccessTokenVO.PROP_GROUP, name);
|
||||
|
||||
if (StringUtils.isBlank(tokenInfo)) {
|
||||
throw new Exception("TokenInfo is NULL");
|
||||
}
|
||||
|
||||
/**
|
||||
* 프로퍼티 OAuthInfo에 프로퍼티 명이 TokenManager에서 관리하는 Key(어댑터그룹명)로 등록
|
||||
* interval, url, client_id, client_secret(암호화), scope, grant_type
|
||||
*
|
||||
* ex) _TST_OU_RST_SyC => {"interval":"86400","url":"oauth/2.0/token","client_id":"l7xx18ddb941fc0d4a6a910f5e132186aa88","client_secret":"18a91f9579994ce8ac10f1aab39ce205","scope":"sa","grant_type":"client_credentials"}
|
||||
*/
|
||||
JSONObject tokenInfoObject = (JSONObject) JSONValue.parse(tokenInfo);
|
||||
|
||||
String oauthAccessTokenUrl = tokenInfoObject.containsKey(OAUTH_ACCESS_TOKEN_URI) ? (String)tokenInfoObject.get(OAUTH_ACCESS_TOKEN_URI) : "";
|
||||
String oauthClientId = tokenInfoObject.containsKey(OAUTH_CLIENT_ID ) ? (String)tokenInfoObject.get(OAUTH_CLIENT_ID ) : "";
|
||||
String oauthClientSecret = tokenInfoObject.containsKey(OAUTH_CLIENT_SECRET ) ? (String)tokenInfoObject.get(OAUTH_CLIENT_SECRET ) : "";
|
||||
String oauthScope = tokenInfoObject.containsKey(OAUTH_SCOPE ) ? (String)tokenInfoObject.get(OAUTH_SCOPE ) : "";
|
||||
String oauthGrantType = tokenInfoObject.containsKey(OAUTH_GRANT_TYPE ) ? (String)tokenInfoObject.get(OAUTH_GRANT_TYPE ) : "";
|
||||
|
||||
//2020-03-12 Scp 모듈 Util로 변경
|
||||
// client_secret를 복호화한다
|
||||
try {
|
||||
oauthClientSecret = ScpDbAgentUtil.ScpDecB64(PropManager.getInstance().getProperties(ScpDbAgentUtil.EXT_MODULE), oauthClientSecret, "EUC-KR");
|
||||
} catch (Exception e) {
|
||||
logger.error("addInboundErrorInfo] scpdb_agent encryption Error - " + e.getMessage());
|
||||
}
|
||||
|
||||
String uri = url + "/" + oauthAccessTokenUrl;
|
||||
String contentType = propManager.getProperty(AccessTokenVO.PROP_GROUP, AccessTokenVO.HEADER_CONTENT_TYPE);
|
||||
|
||||
HttpClient mclient = new HttpClient();
|
||||
PostMethod httpMethod = new PostMethod(uri);
|
||||
|
||||
if(timeout > -1) {
|
||||
httpMethod.getParams().setSoTimeout(timeout);
|
||||
}
|
||||
|
||||
if ( connectionTimeout != 0) {
|
||||
httpMethod.getParams().setParameter("http.connection.timeout", connectionTimeout);
|
||||
}
|
||||
httpMethod.getParams().setParameter("http.protocol.version", HttpVersion.HTTP_1_0);
|
||||
|
||||
try {
|
||||
httpMethod.setParameter(OAUTH_CLIENT_ID , oauthClientId );
|
||||
httpMethod.setParameter(OAUTH_CLIENT_SECRET, oauthClientSecret);
|
||||
httpMethod.setParameter(OAUTH_SCOPE , oauthScope );
|
||||
httpMethod.setParameter(OAUTH_GRANT_TYPE , oauthGrantType );
|
||||
|
||||
httpMethod.setRequestHeader("Content-Type", contentType + "; charset=" + encode);
|
||||
|
||||
logger.debug("HttpClientAccessTokenServiceKFTC] oauthClientId = ["+ oauthClientId +"]");
|
||||
logger.debug("HttpClientAccessTokenServiceKFTC] oauthClientSecret = ["+ oauthClientSecret +"]");
|
||||
logger.debug("HttpClientAccessTokenServiceKFTC] oauthScope = ["+ oauthScope +"]");
|
||||
logger.debug("HttpClientAccessTokenServiceKFTC] oauthGrantType = ["+ oauthGrantType +"]");
|
||||
logger.debug("HttpClientAccessTokenServiceKFTC] contentType = ["+ contentType +"]");
|
||||
logger.debug("HttpClientAccessTokenServiceKFTC] encode = ["+ encode +"]");
|
||||
|
||||
int status = mclient.executeMethod(httpMethod);
|
||||
|
||||
if (status !=200) {
|
||||
throw new Exception ("oauth token receive status fail value= " + status);
|
||||
}
|
||||
|
||||
byte[] responseBody = httpMethod.getResponseBody();
|
||||
String responseString = new String(responseBody, encode);
|
||||
|
||||
OAuth2AccessTokenVO accessToken = new OAuth2AccessTokenVO();
|
||||
|
||||
if (StringUtils.isNotBlank(responseString)) {
|
||||
logger.debug("HttpClientAccessTokenServiceKFTC] oauthToken RECV = ["+ responseString +"]");
|
||||
|
||||
JSONObject responseJSON = (JSONObject) JSONValue.parse(responseString);
|
||||
|
||||
if (responseJSON.containsKey("access_token")
|
||||
&& responseJSON.containsKey("token_type")
|
||||
&& responseJSON.containsKey("expires_in")
|
||||
&& responseJSON.containsKey("scope")) {
|
||||
accessToken.setAccessToken((String) responseJSON.get("access_token"));
|
||||
accessToken.setTokenType ((String) responseJSON.get("token_type" ));
|
||||
|
||||
accessToken.setExpiration (new Date(currentTime + ((BigDecimal)responseJSON.get("expires_in")).longValue()* 1000L));
|
||||
// accessToken.setExpiration (new Date(currentTime + ((long) responseJSON.get("expires_in") * 1000L)));
|
||||
accessToken.setScope ((String) responseJSON.get("scope" ));
|
||||
}
|
||||
|
||||
if (responseJSON.containsKey("client_use_code")) {
|
||||
accessToken.setClientUseCode((String) responseJSON.get("client_use_code"));
|
||||
}
|
||||
|
||||
logger.debug("HttpClientAccessTokenServiceKFTC] oauthToken ="+ accessToken.toString());
|
||||
} else {
|
||||
throw new Exception ("oauth token return null");
|
||||
}
|
||||
|
||||
return accessToken;
|
||||
// 오류 처리 상세화 필요
|
||||
} catch (Exception e) {
|
||||
logger.error("HttpClientAccessTokenServiceKFTC] oauth token fail : " + e.toString() ,e);
|
||||
throw e;
|
||||
} finally {
|
||||
httpMethod.releaseConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
package com.openbanking.eai.common.token.servlet;
|
||||
|
||||
import com.eactive.eai.adapter.AdapterManager;
|
||||
import com.eactive.eai.adapter.AdapterPropManager;
|
||||
import com.eactive.eai.adapter.AdapterVO;
|
||||
import com.eactive.eai.adapter.socket2.common.ExceptionStackTrace;
|
||||
import com.eactive.eai.adapter.socket2.config.SocketAdapterManager;
|
||||
import com.eactive.eai.adapter.socket2.config.SocketLoggerManager;
|
||||
import com.eactive.eai.adapter.socket2.protocol.http.HttpServlet;
|
||||
import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpRequest;
|
||||
import com.eactive.eai.adapter.socket2.protocol.http.codec.HttpResponse;
|
||||
import com.eactive.eai.adapter.socket2.protocol.http.servlet.ThreadDumpUtil;
|
||||
import com.eactive.eai.common.property.PropGroupVO;
|
||||
import com.eactive.eai.common.property.PropManager;
|
||||
import com.eactive.eai.common.util.Logger;
|
||||
import com.openbanking.eai.common.token.AccessTokenManager;
|
||||
import com.openbanking.eai.common.token.AccessTokenVO;
|
||||
import com.openbanking.eai.common.token.OAuth2AccessTokenVO;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JSONValue;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
public class AccessTokenServlet extends HttpServlet {
|
||||
final static SocketAdapterManager manager = SocketAdapterManager.getInstance();
|
||||
static Logger logger = SocketLoggerManager.getInstance().getLogger("FileLogger{NET}_HTTP");
|
||||
|
||||
protected void doService(HttpRequest request, HttpResponse response) throws Exception {
|
||||
String command = request.getContext();
|
||||
if (command.lastIndexOf('/') == -1) {
|
||||
command = "";
|
||||
} else {
|
||||
command = command.substring(command.indexOf('/')+1);
|
||||
}
|
||||
|
||||
String result = "";
|
||||
|
||||
try {
|
||||
String adapterGroupName = request.getParameter("adapter");
|
||||
|
||||
if (command == null || "".equals(command) || "show".equals(command)) {
|
||||
result = show(adapterGroupName);
|
||||
} else if (command.startsWith("refresh")) {
|
||||
logger.fatal("AccessToken | " + adapterGroupName + " | refresh - " + request.getSession());
|
||||
result = refresh(adapterGroupName);
|
||||
} else if (command.startsWith("start")) {
|
||||
logger.fatal("AccessToken | " + adapterGroupName + " | start - " + request.getSession());
|
||||
result = start(adapterGroupName);
|
||||
} else if (command.startsWith("stop")) {
|
||||
logger.fatal("AccessToken | " + adapterGroupName + " | stop - " + request.getSession());
|
||||
result = stop(adapterGroupName);
|
||||
} else {
|
||||
response.setResponseCode(404);
|
||||
return;
|
||||
}
|
||||
|
||||
} catch(Throwable e) {
|
||||
result = "<pre>" + ExceptionStackTrace.dump(e) + "</pre>";
|
||||
}
|
||||
|
||||
response.setContentType("text/html");
|
||||
response.setResponseCode(HttpResponse.HTTP_STATUS_SUCCESS);
|
||||
response.appendBody(result);
|
||||
}
|
||||
|
||||
final static String SCRIPT =
|
||||
" <script> \n" +
|
||||
" function toggle(){ \n" +
|
||||
" var obj = document.getElementsByName(\"action\"); \n" +
|
||||
" if (obj[0].style.display == \"block\"){ \n" +
|
||||
" for (var i=0; i<obj.length; i++ ) { \n" +
|
||||
" obj[i].style.display=\"none\"; \n" +
|
||||
" } \n" +
|
||||
" }else{ \n" +
|
||||
" for (var i=0; i<obj.length; i++ ) { \n" +
|
||||
" obj[i].style.display=\"block\"; \n" +
|
||||
" } \n" +
|
||||
" } \n" +
|
||||
" } \n" +
|
||||
" </script> \n";
|
||||
|
||||
private String show(String adapterGroupName) throws Exception {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(SCRIPT);
|
||||
|
||||
AccessTokenManager manager = AccessTokenManager.getInstance();
|
||||
|
||||
// HashMap<String, AccessTokenVO> tokens = manager.getAllAccessTokenVO();
|
||||
// for (String key : tokens.keySet()) {
|
||||
|
||||
String adapterGroupNameList = manager.getTargetAdapterGroup();
|
||||
String[] adapterGroupNames = adapterGroupNameList.split("[,]");
|
||||
|
||||
ThreadGroup it = Thread.currentThread().getThreadGroup();
|
||||
Thread[] threads = new Thread[it.activeCount()] ;
|
||||
it.enumerate(threads);
|
||||
|
||||
for (String key : adapterGroupNames) {
|
||||
if (adapterGroupName != null && !"".equals(adapterGroupName) && adapterGroupName.indexOf(key) < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sb.append("¨Ó <b>" + key + "</b>");
|
||||
|
||||
String status = manager.getStatus(key);
|
||||
|
||||
if ("STARTED".equals(status)) {
|
||||
sb.append(" (" + status + ")");
|
||||
} else {
|
||||
sb.append(" <b>(" + status + ")</b>");
|
||||
}
|
||||
|
||||
sb.append("<div name=\"action\" style=\"display:none\">");
|
||||
sb.append(" (<a href='/token/refresh?adapter=" + key + "'>refresh</a>");
|
||||
sb.append("|<a href='/token/start?adapter=" + key + "'>start</a>");
|
||||
sb.append("|<a href='/token/stop?adapter=" + key + "'>stop</a>)");
|
||||
sb.append("</div>");
|
||||
|
||||
sb.append("\n");
|
||||
|
||||
OAuth2AccessTokenVO token = (OAuth2AccessTokenVO) manager.getAccessTokenVO(key);
|
||||
|
||||
if (token != null) {
|
||||
sb.append(String.format("%4s %-20s : %s\n", "", "access_token", token.getAccessToken()));
|
||||
sb.append(String.format("%4s %-20s : %s\n", "", "expiration", token.getExpiration()));
|
||||
sb.append(String.format("%4s %-20s : %s\n", "", "is_expired", token.isExpired()));
|
||||
sb.append(String.format("%4s %-20s : %s\n", "", "scope", token.getScope()));
|
||||
sb.append(String.format("%4s %-20s : %s\n", "", "token_type", token.getTokenType()));
|
||||
sb.append(String.format("%4s %-20s : %s\n", "", "client_use_code", token.getClientUseCode()));
|
||||
}
|
||||
|
||||
PropGroupVO vo = PropManager.getInstance().getPropGroupVO(AccessTokenVO.PROP_GROUP);
|
||||
String tokenInfo = vo.getProperty(key);
|
||||
|
||||
if (tokenInfo != null) {
|
||||
sb.append("\n");
|
||||
|
||||
JSONObject tokenInfoObject = (JSONObject) JSONValue.parse(tokenInfo);
|
||||
|
||||
int interval = Integer.parseInt(tokenInfoObject.get("interval") != null ? (String) tokenInfoObject.get("interval") : "0");
|
||||
String hms = "sec";
|
||||
|
||||
if (interval / 60 / 60 > 1) {
|
||||
interval = interval / 60 / 60;
|
||||
hms = "hour";
|
||||
} else if (interval / 60 > 1) {
|
||||
interval = interval / 60;
|
||||
hms = "min";
|
||||
}
|
||||
|
||||
boolean adapter = false;
|
||||
String url = (String) tokenInfoObject.get("url");
|
||||
|
||||
try {
|
||||
AdapterVO avo = (AdapterVO) AdapterManager.getInstance().getAdapterGroupVO(key).getAdapters().next();
|
||||
Properties properties = AdapterPropManager.getInstance().getProperties(avo.getPropGroupName());
|
||||
url = properties.getProperty("URL") + "/" + url;
|
||||
|
||||
adapter = true;
|
||||
} catch (Exception ignore) {
|
||||
adapter = false;;
|
||||
}
|
||||
|
||||
sb.append(String.format("%4s %-20s : %s\n", "", "adapter", adapter));
|
||||
sb.append(String.format("%4s %-20s : %s %s\n", "", "interval", interval, hms));
|
||||
sb.append(String.format("%4s %-20s : %s\n", "", "url", url));
|
||||
sb.append(String.format("%4s %-20s : %s\n", "", "grant_type", (String) tokenInfoObject.get("grant_type")));
|
||||
}
|
||||
|
||||
/**
|
||||
* threads info
|
||||
*/
|
||||
sb.append("\n<b> threads</b>");
|
||||
sb.append("\n<font color='gray'>");
|
||||
sb.append("<table border='0' style='padding-left:25px'>");
|
||||
for (int i=0; i<threads.length; i++) {
|
||||
try {
|
||||
if ((threads[i] != null && threads[i].getName() != null && threads[i].getName().startsWith(key + "-AccessToken"))) {
|
||||
sb.append("<tr>");
|
||||
sb.append(ThreadDumpUtil.getStackTrace(threads[i]));
|
||||
sb.append("</tr>");
|
||||
}
|
||||
} catch(Exception e) {
|
||||
logger.error("Error", e) ;
|
||||
}
|
||||
}
|
||||
sb.append("</table>");
|
||||
sb.append("</font>");
|
||||
sb.append("\n");
|
||||
sb.append("\n");
|
||||
|
||||
// String filter = key + "-AccessToken";
|
||||
// sb.append("<tr><td style='padding-left:20px; padding-bottom:20px'>");
|
||||
// sb.append(ThreadDumpUtil.dump(filter));
|
||||
// sb.append("</td></tr>");
|
||||
}
|
||||
|
||||
sb.append("<span style=\"color:white\" ondblclick=\"toggle()\">button</span>");
|
||||
|
||||
return "<pre>" + sb.toString() + "</pre>";
|
||||
}
|
||||
|
||||
private String refresh(String adapterGroupName) throws Exception {
|
||||
|
||||
AccessTokenManager manager = AccessTokenManager.getInstance();
|
||||
|
||||
// String token = manager.getAccessToken(adapterGroupName);
|
||||
// if (token == null)
|
||||
// return "<pre>token not exist</pre>";
|
||||
|
||||
manager.refresh(adapterGroupName, true);
|
||||
|
||||
return adapterGroupName + " | successfully refreshed";
|
||||
}
|
||||
|
||||
private String start(String adapterGroupName) throws Exception {
|
||||
|
||||
AccessTokenManager manager = AccessTokenManager.getInstance();
|
||||
manager.startToken(adapterGroupName);
|
||||
|
||||
return adapterGroupName + " | successfully started";
|
||||
}
|
||||
|
||||
private String stop(String adapterGroupName) throws Exception {
|
||||
|
||||
AccessTokenManager manager = AccessTokenManager.getInstance();
|
||||
manager.stopToken(adapterGroupName);
|
||||
|
||||
return adapterGroupName + " | successfully stoped";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user