RootlessArray 키추가 관련 필터, HMAC필터와 맞추기위해 byte[]처리.

This commit is contained in:
cho
2026-01-15 09:08:12 +09:00
parent cfb1c7c692
commit a7047c2523
@@ -1,20 +1,28 @@
package com.eactive.eai.adapter.controller;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import com.eactive.eai.adapter.AdapterGroupVO;
import com.eactive.eai.adapter.AdapterManager;
import com.eactive.eai.adapter.http.dynamic.HttpDynamicInAdapterManager;
import com.eactive.eai.adapter.http.dynamic.HttpDynamicInAdapterUri;
import com.eactive.eai.common.stdmessage.STDMessageManager;
import com.eactive.eai.common.stdmessage.STDMsgInfoAddOnVO;
public class ApiRequestBodyFilter extends OncePerRequestFilter {
@@ -23,63 +31,119 @@ public class ApiRequestBodyFilter extends OncePerRequestFilter {
HttpServletResponse response,
FilterChain filterChain)
throws ServletException, IOException {
// 1. 필터 대상
String encoding = getInboundGroupAdapterEncoding(request);
if (!isTarget(request)) {
filterChain.doFilter(request, response);
return;
}
// 2. 요청 전문 읽기
String body = readBody(request);
if (body == null || body.isEmpty()) {
//원본 바디를 byte[]로 읽기 (개행 포함 그대로) 왜? 뒤에 필터에서 HMAC값 계산할수도 있어서 변조되면 안됨. 개행문자도 그대로 가야함.
byte[] rawBody = readBodyAsBytes(request);
if (rawBody == null || rawBody.length == 0) {
filterChain.doFilter(request, response);
return;
}
String modifiedBody = body;
byte[] finalBody = rawBody;
try {
Object json = JSONValue.parse(body);
// 3. 예제: ROOTLESS ARRAY 보정
String bodyStr = new String(rawBody, encoding);
Object json = JSONValue.parse(bodyStr);
if (json instanceof JSONArray) {
JSONObject wrap = new JSONObject();
wrap.put("KJB_ROOTLESS_ARRAY", json);
modifiedBody = wrap.toJSONString();
finalBody = wrap.toJSONString().getBytes(encoding);
}
} catch (Exception e) {
// 변조 실패 원본 유지
modifiedBody = body;
// JSON 파싱 실패 원본 유지
finalBody = rawBody;
}
byte[] bytes = modifiedBody.getBytes(request.getCharacterEncoding() != null ? request.getCharacterEncoding() : Charset.defaultCharset().name() );
// 5. Wrapper로 재주입
// Wrapper로 재주입
HttpServletRequest wrapped =
new CachedBodyHttpServletRequest(request, bytes);
new CachedBodyHttpServletRequest(request, finalBody);
filterChain.doFilter(wrapped, response);
}
private boolean isTarget(HttpServletRequest request) {
String uri = request.getRequestURI();
return ("POST".equals(request.getMethod()) || "PUT".equals(request.getMethod()))
&& (uri.startsWith("/api") || uri.startsWith("/mapi") ) && !uri.startsWith("/mapi/oauth2/token");
&& (uri.startsWith("/api") || uri.startsWith("/mapi"))
&& !uri.startsWith("/mapi/oauth2/token");
}
private String readBody(HttpServletRequest request) throws IOException {
StringBuilder sb = new StringBuilder();
try (BufferedReader br = request.getReader()) {
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
private byte[] readBodyAsBytes(HttpServletRequest request) throws IOException {
try (ServletInputStream is = request.getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
byte[] buffer = new byte[4096];
int len;
while ((len = is.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
return baos.toByteArray();
}
}
private String getInboundGroupAdapterEncoding(HttpServletRequest request) {
String apiUri = request.getRequestURI();
apiUri = StringUtils.removeStart(apiUri, request.getContextPath());
apiUri = StringUtils.removeEnd(apiUri, "/");
String methodAndUri = request.getMethod() + "|" + apiUri;
String adapterGrpName;
HttpDynamicInAdapterUri adptUri = null;
try {
STDMessageManager manager = STDMessageManager.getInstance();
STDMsgInfoAddOnVO stdMsgInfo = manager.getStdMsgInfoAddOn(methodAndUri);
adapterGrpName = stdMsgInfo.gAdapterGroupName();
adptUri = findAdptUri(apiUri, HttpDynamicInAdapterManager.getInstance(), adapterGrpName);
} catch (Exception e) {
adptUri = null;
}
AdapterGroupVO adapterGroupVO = AdapterManager.getInstance().getAdapterGroupVO( adptUri.getAdptGrpName());
if( adapterGroupVO == null ) {
return Charset.defaultCharset().name();
}
return StringUtils.isNotBlank(adapterGroupVO.getMessageEncode()) ? adapterGroupVO.getMessageEncode() : Charset.defaultCharset().name(); //서버 jvm file.encoding 확인, file.encoding=utf-8 주고있음.
}
private HttpDynamicInAdapterUri findAdptUri(String apiUri, HttpDynamicInAdapterManager manager, String adapterGrpName) throws Exception {
if (StringUtils.isBlank(apiUri)) {
return null;
}
for (int i = 0; i < 10; i++) {
HttpDynamicInAdapterUri adptUri = manager.getAdptUri(apiUri);
if (adptUri != null) {
if (adptUri.getAdptGrpName().equals(adapterGrpName)) {
return adptUri;
}
}
apiUri = StringUtils.substringBeforeLast(apiUri, "/");
if (apiUri.length() < 4) { // /api
return null;
}
}
return sb.toString();
}
}
return null;
}
}