This commit is contained in:
eastargh
2026-09-04 11:29:47 +09:00
5 changed files with 47 additions and 150 deletions
@@ -1,64 +0,0 @@
package com.eactive.eai.rms.common.interceptor;
import com.eactive.apim.portal.portalproperty.service.PortalPropertyService;
import java.io.IOException;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
@Component
@Slf4j
public class ApiKeyInterceptor implements HandlerInterceptor {
private static final String API_KEY_HEADER = "X-API-KEY";
private static final String PORTAL_PROPERTY_GROUP = "Portal";
@Autowired
private PortalPropertyService portalPropertyService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
try {
String requestApiKey = request.getHeader(API_KEY_HEADER);
if (StringUtils.isEmpty(requestApiKey)) {
log.warn("Request received without API key. URI: {}", request.getRequestURI());
sendErrorResponse(response, HttpServletResponse.SC_UNAUTHORIZED, "API key is missing");
return false;
}
Map<String, String> properties = portalPropertyService.getPortalPropertiesAsMap(PORTAL_PROPERTY_GROUP);
String validApiKey = properties.get("apiKey");
if (StringUtils.isEmpty(validApiKey)) {
log.error("API key not configured in properties");
sendErrorResponse(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "API key is not configured");
return false;
}
if (!validApiKey.equals(requestApiKey)) {
log.warn("Invalid API key received. URI: {}", request.getRequestURI());
sendErrorResponse(response, HttpServletResponse.SC_FORBIDDEN, "Invalid API key");
return false;
}
return true;
} catch (Exception e) {
log.error("Error processing API key validation", e);
sendErrorResponse(response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error processing request");
return false;
}
}
private void sendErrorResponse(HttpServletResponse response, int status, String message) throws IOException {
response.setStatus(status);
response.setContentType("application/json");
response.getWriter().write(String.format("{\"error\": \"%s\"}", message));
}
}
@@ -0,0 +1,44 @@
package com.eactive.eai.rms.common.interceptor;
import com.eactive.apim.portal.common.internal.InternalApiTokenService;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
/**
* {@code /_onl/**} 내부 연동 요청을 공유 내부 토큰으로 검증한다.
*
* <p>토큰과 헤더명은 PTL_PROPERTY {@code Portal / internal.api.header-name},
* {@code Portal / internal.api.token}을 사용한다. admin은 토큰을 생성하지 않고 읽기 전용으로
* 검증하므로, portal이 먼저 기동되어 토큰을 생성해야 한다.</p>
*/
@Component
@RequiredArgsConstructor
@Slf4j
public class InternalApiTokenInterceptor implements HandlerInterceptor {
private final InternalApiTokenService internalApiTokenService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
String headerName = internalApiTokenService.findHeaderName();
String presentedToken = request.getHeader(headerName);
if (!internalApiTokenService.matchesReadOnly(presentedToken)) {
log.warn("Invalid internal API token. URI: {}, header: {}", request.getRequestURI(), headerName);
sendErrorResponse(response, HttpServletResponse.SC_UNAUTHORIZED, "Internal API token is invalid");
return false;
}
return true;
}
private void sendErrorResponse(HttpServletResponse response, int status, String message) throws IOException {
response.setStatus(status);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(String.format("{\"error\": \"%s\"}", message));
}
}
@@ -6,7 +6,6 @@ import com.eactive.apim.portal.approval.statemachine.listener.ApprovalListener;
import com.eactive.apim.portal.portalorg.entity.PortalOrg;
import com.eactive.apim.portal.portalorg.entity.PortalOrgEnums.ApprovalStatus;
import com.eactive.apim.portal.portalorg.entity.PortalOrgEnums.OrgStatus;
import com.eactive.apim.portal.portalproperty.service.PortalPropertyService;
import com.eactive.apim.portal.portaluser.entity.PortalUser;
import com.eactive.apim.portal.portaluser.entity.PortalUserEnums;
import com.eactive.apim.portal.template.entity.MessageCode;
@@ -14,27 +13,15 @@ import com.eactive.apim.portal.template.service.MessageRecipient;
import com.eactive.apim.portal.template.service.MessageSendService;
import com.eactive.eai.rms.data.entity.onl.apim.portalorg.PortalOrgService;
import com.eactive.eai.rms.data.entity.onl.apim.portaluser.PortalUserService;
import com.eactive.eai.rms.onl.apim.portalorg.PortalOrgUI;
import com.eactive.eai.rms.onl.apim.portalorg.PortalOrgUIMapper;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.HttpClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
@Service
@Transactional
@@ -42,36 +29,9 @@ import org.springframework.web.client.RestTemplate;
public class PortalUserApprovalListener implements ApprovalListener {
private static final Logger logger = LoggerFactory.getLogger(PortalUserApprovalListener.class);
private static final String PORTAL_PROPERTY_GROUP = "Portal";
private final PortalPropertyService portalPropertyService;
private final PortalOrgService portalOrgService;
private final PortalUserService portalUserService;
private final MessageSendService messageSendService;
private final PortalOrgUIMapper portalOrgUIMapper;
public static RestTemplate createRestTemplateWithTimeout(int connectTimeout) {
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(connectTimeout)
.setConnectTimeout(connectTimeout)
.setSocketTimeout(connectTimeout)
.build();
HttpClient httpClient =
HttpClientBuilder.create()
.setMaxConnTotal(50)
.setMaxConnPerRoute(20)
.setDefaultRequestConfig(requestConfig)
.build();
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setHttpClient(httpClient);
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(factory);
return restTemplate;
}
@Override
public void execute(Approval approval, Map<String, Object> options) throws ApprovalDeployException {
@@ -88,7 +48,6 @@ public class PortalUserApprovalListener implements ApprovalListener {
portalOrg.setOrgStatus(OrgStatus.ACTIVE);
portalOrgService.save(portalOrg);
// syncStaging(portalOrgUIMapper.toVo(portalOrg));
sendApprovalResult(portalUser);
}
@@ -106,48 +65,6 @@ public class PortalUserApprovalListener implements ApprovalListener {
messageSendService.sendMessage(MessageCode.MANAGER_WITH_ORG_REGISTER_APPROVED, recipient, params);
}
/**
* @deprecated 광주은행에서는 사용하지 않음. (개발/운영 완전 분리)
* @param portalOrgUI
* @throws ApprovalDeployException
*/
private void syncStaging(PortalOrgUI portalOrgUI) throws ApprovalDeployException {
throw new RuntimeException("Unable use this method(syncStaging())");
// // 프록시를 통한 스테이징 서버 호출 추가
// Map<String, String> properties = portalPropertyService.getPortalPropertiesAsMap(PORTAL_PROPERTY_GROUP);
// String apiKey = properties.get("apiKey");
// String proxyUrl = properties.get("portal.url");
// String timeout = properties.getOrDefault("deploy.proxy_timeout", "10000");
// String proxyEndpoint = proxyUrl + "/_onl/apim/portalorg/portalOrgMan.json";
//
// HttpHeaders headers = new HttpHeaders();
// headers.setContentType(MediaType.APPLICATION_JSON);
// headers.set("X-API-KEY", apiKey);
// headers.set("target_host", "stg");
// headers.set("action", "insert");
//
// portalOrgUI.setCompRegFile(null);
// HttpEntity<PortalOrgUI> request = new HttpEntity<>(portalOrgUI, headers);
//
// try {
// ResponseEntity<String> response = createRestTemplateWithTimeout(Integer.parseInt(timeout)).exchange(
// proxyEndpoint,
// HttpMethod.POST,
// request,
// String.class
// );
//
// if (!response.getStatusCode().is2xxSuccessful()) {
// logger.error("Failed to sync with staging server. Status: {}, Body: {}", response.getStatusCode(), response.getBody());
// throw new ApprovalDeployException("기관 정보 배포에 실패 했습니다.");
// }
// } catch (Exception e) {
// logger.error("Failed to sync with staging server. {}", e.getMessage());
// throw new ApprovalDeployException("기관 정보 배포에 실패 했습니다.");
// }
}
@Override
public void rollback(Approval approval) {
logger.debug("Rollback started for approval ID: {}, type: {}, status: {}",