From f8523658053a3ab03aef3fdc701724ffe3075710 Mon Sep 17 00:00:00 2001 From: bjkim Date: Wed, 29 Oct 2025 12:47:58 +0900 Subject: [PATCH] =?UTF-8?q?[MODIFY]=20ExternalAuthService=EC=97=90=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EB=B0=8F=20=EB=A1=9C=EA=B7=B8=20=EC=B6=94=EA=B0=80,=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=20=EA=B2=80=EC=A6=9D=20=EB=B0=8F=20URL=20?= =?UTF-8?q?=EA=B5=AC=EC=84=B1=20=EB=A1=9C=EC=A7=81=20=EA=B0=84=EC=86=8C?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../autoflow/service/ExternalAuthService.java | 44 ++++++++++++++----- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/src/main/java/kr/re/etri/autoflow/service/ExternalAuthService.java b/src/main/java/kr/re/etri/autoflow/service/ExternalAuthService.java index 0f57a88..5bb3efe 100644 --- a/src/main/java/kr/re/etri/autoflow/service/ExternalAuthService.java +++ b/src/main/java/kr/re/etri/autoflow/service/ExternalAuthService.java @@ -3,6 +3,7 @@ package kr.re.etri.autoflow.service; import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.annotation.PostConstruct; import kr.re.etri.autoflow.payload.request.EdgeSWVO; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.core.io.ByteArrayResource; import org.springframework.http.*; @@ -11,6 +12,7 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpServerErrorException; +import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.web.multipart.MultipartFile; @@ -22,9 +24,11 @@ import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.security.cert.X509Certificate; import java.util.HashMap; +import java.util.List; import java.util.Map; @Service +@Slf4j public class ExternalAuthService { private RestTemplate restTemplate; @@ -161,7 +165,7 @@ public class ExternalAuthService { */ public Map getSWPackageList(String id, String token) { try { - // 1) 입력 검증: id에 URL/공격 문자열 포함 금지 + // 1) 입력 검증 if (id == null || id.isBlank()) { throw new IllegalArgumentException("잘못된 사용자 ID입니다."); } @@ -169,15 +173,15 @@ public class ExternalAuthService { throw new IllegalArgumentException("ID에 URL을 포함할 수 없습니다."); } - // 2) 안전하게 파라미터 인코딩 및 URL 구성 (base URL은 외부 입력에서 분리) + // 2) URL 구성 String safeId = URLEncoder.encode(id, StandardCharsets.UTF_8); - String url = String.format("%s?sw_group=-1&sw_type=-1&searchType=&searchText=&pageNum=1&pageSize=10&auth_id=%s&user_id=", + String url = String.format( + "%s?sw_group=-1&sw_type=-1&searchType=&searchText=&pageNum=1&pageSize=10&auth_id=%s&user_id=", swSearchUrl, safeId); - // 3) URI 생성 (edgeSearchUrl이 올바른 형식인지 확인) URI uri = URI.create(url); - // 추가 안전권장(선택) : 실제 호출되는 호스트가 설정한 base URL의 호스트와 동일한지 확인 + // 3) 호스트 검증 URI baseUri = URI.create(swSearchUrl); if (!uri.getHost().equalsIgnoreCase(baseUri.getHost())) { throw new SecurityException("요청 호스트가 허용된 서비스와 일치하지 않습니다."); @@ -186,7 +190,7 @@ public class ExternalAuthService { // 4) 요청 헤더 구성 HttpHeaders headers = new HttpHeaders(); headers.setBearerAuth(token); - headers.setAccept(java.util.List.of(MediaType.APPLICATION_JSON)); + headers.setAccept(List.of(MediaType.APPLICATION_JSON)); HttpEntity request = new HttpEntity<>(headers); // 5) 요청 수행 @@ -195,15 +199,31 @@ public class ExternalAuthService { if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) { return response.getBody(); } else { - throw new RuntimeException("외부 Edge 패키지 조회 실패"); + throw new RuntimeException("외부 SW 패키지 조회 실패: " + response.getStatusCode()); } - } catch (IllegalArgumentException iae) { - // 입력 검증 실패는 호출자에게 명확히 알릴 수 있음 - throw iae; + } catch (IllegalArgumentException | SecurityException ex) { + // 입력 관련 예외는 그대로 던짐 + throw ex; + } catch (HttpClientErrorException httpEx) { + // 4xx (예: 401, 403, 404) + log.error("[SW API 호출 오류 - 클라이언트 측] Status: {}, Body: {}", + httpEx.getStatusCode(), httpEx.getResponseBodyAsString(), httpEx); + throw new RuntimeException("SW API 4xx 오류: " + httpEx.getStatusCode() + " - " + httpEx.getResponseBodyAsString(), httpEx); + } catch (HttpServerErrorException serverEx) { + // 5xx (서버 내부 오류) + log.error("[SW API 호출 오류 - 서버 측] Status: {}, Body: {}", + serverEx.getStatusCode(), serverEx.getResponseBodyAsString(), serverEx); + throw new RuntimeException("SW API 5xx 오류: " + serverEx.getStatusCode() + " - " + serverEx.getResponseBodyAsString(), serverEx); + } catch (ResourceAccessException connEx) { + // 네트워크/연결 예외 + log.error("[SW API 호출 오류 - 연결 불가]", connEx); + throw new RuntimeException("SW API 연결 실패: " + connEx.getMessage(), connEx); } catch (Exception e) { - // 내부 상세 예외는 래핑하여 외부에 노출하지 않음 - throw new RuntimeException("외부 Edge API 호출 중 오류가 발생했습니다."); + // 그 외 모든 예외 + log.error("[SW API 호출 중 알 수 없는 오류 발생]", e); + throw new RuntimeException("외부 SW API 호출 중 내부 오류: " + e.getClass().getSimpleName() + " - " + e.getMessage(), e); } } + }