ToolsController 개발

- base64 인코딩, damo 암복호화, version 정보
This commit is contained in:
curry772
2026-07-23 11:43:59 +09:00
parent cb0a588a9c
commit 9e1f7391a0
8 changed files with 901 additions and 0 deletions
@@ -0,0 +1,15 @@
package com.eactive.eai.manage.tools;
import lombok.Data;
/**
* EncryptionManager의 현재 설정 상태. encrypt/decrypt 결과가 원문 그대로인 이유
* (encryptYN=N이면 encryptDBData가 원문을 그대로 반환)를 함께 확인하기 위한 진단 정보다.
*/
@Data
public class EncryptionManagerStatusDTO {
String encryptYN;
String dbEncryptSolutionName;
boolean encryptEnabled;
}
@@ -0,0 +1,123 @@
package com.eactive.eai.manage.tools;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
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.RestController;
/**
* base64 / hex / DAMO 변환을 브라우저나 Postman 등에서 바로 테스트할 수 있는 유틸리티 API.
*
* POST /manage/tools/base64/encode → 문자열 → Base64
* POST /manage/tools/base64/decode → Base64 → 문자열
* POST /manage/tools/hex/encode → 문자열 → Hex
* POST /manage/tools/hex/decode → Hex → 문자열
* POST /manage/tools/damo/encrypt → 평문 → DAMO 암호문 (DamoManager 직접 호출)
* POST /manage/tools/damo/decrypt → DAMO 암호문 → 평문 (DamoManager 직접 호출)
*
* POST /manage/tools/encryption-manager/encrypt → EncryptionManager.encryptDBData 확인용
* POST /manage/tools/encryption-manager/decrypt → EncryptionManager.decryptDBData 확인용
* GET /manage/tools/encryption-manager/status → encryptYN/dbEncryptSolutionName 등 현재 설정 확인
*
* GET /manage/tools/version → 배포된 게이트웨이(eapim-online.war)의 git 버전/빌드시각 확인.
* eapim-online(WAR를 만드는 루트 프로젝트) build.gradle의
* generateVersionInfo 태스크가 생성하는 classpath 리소스
* version.info(git describe 결과) 기반. 재빌드 없이 기동한 로컬
* 환경 등 파일이 없으면 success=false로 응답한다
*
* base64/hex 변환은 요청 body의 charset(생략 시 UTF-8)을 기준으로 문자열 ↔ 바이트를 변환한다.
*/
@RestController
@RequestMapping("/manage/tools")
public class ToolsController {
private static final MediaType APPLICATION_JSON_UTF8 = new MediaType("application", "json", StandardCharsets.UTF_8);
@Autowired
private ToolsService toolsService;
@PostMapping("/base64/encode")
public ResponseEntity<?> base64Encode(@RequestBody ToolsTextRequestDTO request) {
return respond(() -> toolsService.base64Encode(request.getText(), request.getCharset()));
}
@PostMapping("/base64/decode")
public ResponseEntity<?> base64Decode(@RequestBody ToolsTextRequestDTO request) {
return respond(() -> toolsService.base64Decode(request.getText(), request.getCharset()));
}
@PostMapping("/hex/encode")
public ResponseEntity<?> hexEncode(@RequestBody ToolsTextRequestDTO request) {
return respond(() -> toolsService.hexEncode(request.getText(), request.getCharset()));
}
@PostMapping("/hex/decode")
public ResponseEntity<?> hexDecode(@RequestBody ToolsTextRequestDTO request) {
return respond(() -> toolsService.hexDecode(request.getText(), request.getCharset()));
}
@PostMapping("/damo/encrypt")
public ResponseEntity<?> damoEncrypt(@RequestBody ToolsTextRequestDTO request) {
return respond(() -> toolsService.damoEncrypt(request.getText()));
}
@PostMapping("/damo/decrypt")
public ResponseEntity<?> damoDecrypt(@RequestBody ToolsTextRequestDTO request) {
return respond(() -> toolsService.damoDecrypt(request.getText()));
}
@PostMapping("/encryption-manager/encrypt")
public ResponseEntity<?> encryptionManagerEncrypt(@RequestBody ToolsTextRequestDTO request) {
return respond(() -> toolsService.encryptionManagerEncrypt(request.getText()));
}
@PostMapping("/encryption-manager/decrypt")
public ResponseEntity<?> encryptionManagerDecrypt(@RequestBody ToolsTextRequestDTO request) {
return respond(() -> toolsService.encryptionManagerDecrypt(request.getText()));
}
@GetMapping("/encryption-manager/status")
public ResponseEntity<?> encryptionManagerStatus() {
return respond(() -> toolsService.encryptionManagerStatus());
}
@GetMapping("/version")
public ResponseEntity<?> getVersionInfo() {
Map<String, Object> result = new HashMap<>();
try {
VersionInfoDTO versionInfo = toolsService.getVersionInfo();
if (versionInfo == null) {
result.put("success", false);
result.put("message", "version.info 파일이 없습니다. gradle의 generateVersionInfo 태스크(또는 build) 실행 후 재기동하세요.");
} else {
result.put("success", true);
result.put("data", versionInfo);
}
} catch (Exception e) {
result.put("success", false);
result.put("message", e.getMessage());
}
return ResponseEntity.ok().contentType(APPLICATION_JSON_UTF8).body(result);
}
private ResponseEntity<?> respond(Callable<Object> action) {
Map<String, Object> result = new HashMap<>();
try {
result.put("success", true);
result.put("data", action.call());
} catch (Exception e) {
result.put("success", false);
result.put("message", e.getMessage());
}
return ResponseEntity.ok().contentType(APPLICATION_JSON_UTF8).body(result);
}
}
@@ -0,0 +1,126 @@
package com.eactive.eai.manage.tools;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;
import javax.xml.bind.DatatypeConverter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import com.eactive.eai.agent.encryption.EncryptionManager;
/**
* base64 / hex / DAMO 변환을 테스트하기 위한 서비스.
*
* DAMO 암복호화는 EncryptionManager와 동일하게 com.eactive.ext.djb.DamoManager를 직접 사용한다.
* EncryptionManager.encryptDBData/decryptDBData는 encryptYN=Y로 설정된 환경에서만 동작하므로
* (비활성 환경에서는 원문을 그대로 반환), 환경 설정과 무관하게 항상 실제 암복호화를 확인할 수 있도록
* DamoManager를 직접 호출한다.
*
* encryptionManagerEncrypt/Decrypt는 위와 별개로, 실제 운영 코드가 사용하는
* EncryptionManager.encryptDBData/decryptDBData를 그대로 호출해 현재 서버 설정(encryptYN,
* dbEncryptSolutionName)이 반영된 실제 동작을 확인하기 위한 용도다.
*/
@Service
public class ToolsService {
private static final String MODULE_KEY_PREFIX = "module.";
private Charset resolveCharset(String charset) {
return StringUtils.isNotBlank(charset) ? Charset.forName(charset) : StandardCharsets.UTF_8;
}
public String base64Encode(String text, String charset) {
byte[] bytes = text.getBytes(resolveCharset(charset));
return Base64.getEncoder().encodeToString(bytes);
}
public String base64Decode(String base64Text, String charset) {
byte[] bytes = Base64.getDecoder().decode(base64Text);
return new String(bytes, resolveCharset(charset));
}
public String hexEncode(String text, String charset) {
byte[] bytes = text.getBytes(resolveCharset(charset));
return DatatypeConverter.printHexBinary(bytes);
}
public String hexDecode(String hexText, String charset) {
byte[] bytes = DatatypeConverter.parseHexBinary(hexText.trim());
return new String(bytes, resolveCharset(charset));
}
public String damoEncrypt(String text) {
return new com.eactive.ext.djb.DamoManager().encrypt(text);
}
public String damoDecrypt(String text) {
return new com.eactive.ext.djb.DamoManager().decrypt(text);
}
public String encryptionManagerEncrypt(String text) {
return EncryptionManager.getInstance().encryptDBData(text);
}
public String encryptionManagerDecrypt(String text) {
return EncryptionManager.getInstance().decryptDBData(text);
}
public EncryptionManagerStatusDTO encryptionManagerStatus() {
EncryptionManager manager = EncryptionManager.getInstance();
EncryptionManagerStatusDTO status = new EncryptionManagerStatusDTO();
status.setEncryptYN(manager.getEncryptYN());
status.setDbEncryptSolutionName(manager.getDBEncryptSolutionName());
status.setEncryptEnabled(manager.isEncrypt());
return status;
}
/**
* eapim-online(WAR를 생성하는 루트 프로젝트) build.gradle의 generateVersionInfo 태스크가
* processResources 이전에 생성하는 classpath 리소스 version.info(version=git describe 결과,
* buildTime=...)를 읽는다. WAR는 WEB-INF/classes와 WEB-INF/lib가 클래스로더를 공유하므로
* 이 클래스(elink-online-common 모듈)에서 조회해도 정상적으로 찾을 수 있다.
* 재빌드 없이 IDE에서 바로 기동한 로컬 환경 등 파일이 없는 경우 null을 반환한다.
*/
public VersionInfoDTO getVersionInfo() {
try (InputStream in = getClass().getResourceAsStream("/version.info")) {
if (in == null) {
return null;
}
return parseVersionInfo(in);
} catch (IOException e) {
throw new RuntimeException("version.info 읽기 실패", e);
}
}
/** version.info 내용을 파싱한다. 리소스 조회와 분리해 테스트에서 직접 검증할 수 있게 한다. */
VersionInfoDTO parseVersionInfo(InputStream in) throws IOException {
Properties props = new Properties();
// Properties.load(InputStream)은 ISO-8859-1로 고정 해석되어 UTF-8로 기록된
// version.info의 한글(git tag 등)이 깨진다. Reader로 감싸 UTF-8로 디코딩해서 넘긴다.
props.load(new InputStreamReader(in, StandardCharsets.UTF_8));
VersionInfoDTO dto = new VersionInfoDTO();
dto.setVersion(props.getProperty("version"));
dto.setBuildTime(props.getProperty("buildTime"));
// module.<서브모듈명>=<git describe 결과> 형태의 키를 모아 서브모듈별 버전으로 담는다.
Map<String, String> moduleVersions = new TreeMap<>();
for (String key : props.stringPropertyNames()) {
if (key.startsWith(MODULE_KEY_PREFIX)) {
moduleVersions.put(key.substring(MODULE_KEY_PREFIX.length()), props.getProperty(key));
}
}
dto.setModuleVersions(moduleVersions);
return dto;
}
}
@@ -0,0 +1,16 @@
package com.eactive.eai.manage.tools;
import lombok.Data;
/**
* base64/hex/damo 변환 테스트 요청 DTO.
*
* charset은 base64/hex 변환에서 문자열 ↔ 바이트 변환에 사용되며, 생략 시 UTF-8이 적용된다.
* damo 암복호화는 String 기반 API(DamoManager)를 그대로 사용하므로 charset을 사용하지 않는다.
*/
@Data
public class ToolsTextRequestDTO {
String text;
String charset;
}
@@ -0,0 +1,25 @@
package com.eactive.eai.manage.tools;
import java.util.Map;
import lombok.Data;
/**
* 빌드 시점에 생성되는 version.info(classpath 리소스) 내용을 담는 DTO.
* eapim-online(WAR 루트 프로젝트) build.gradle의 generateVersionInfo 태스크가
* processResources 이전에 생성한다.
*/
@Data
public class VersionInfoDTO {
/** git describe --tags --always --dirty 결과 (예: 20260722_개발배포, 또는 태그 없으면 커밋 해시). */
String version;
String buildTime;
/**
* elink-online-common 등 git submodule 각각의 git describe 결과.
* 키는 submodule 디렉토리명(elink-online-common 등), 값은 describe 결과.
* 루트(eapim-online)의 describe/dirty만으로는 어느 서브모듈이 바뀌었는지 알 수 없어서 별도로 담는다.
*/
Map<String, String> moduleVersions;
}