package com.zy.acs.manager.common.interceptor;
|
|
import com.zy.acs.framework.common.Cools;
|
import com.zy.acs.manager.common.annotation.IntegrationAuth;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.core.annotation.AnnotatedElementUtils;
|
import org.springframework.stereotype.Component;
|
import org.springframework.web.method.HandlerMethod;
|
import org.springframework.web.servlet.HandlerInterceptor;
|
import org.springframework.web.util.ContentCachingRequestWrapper;
|
|
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletResponse;
|
import java.nio.charset.Charset;
|
import java.nio.charset.StandardCharsets;
|
import java.util.Arrays;
|
import java.util.Collections;
|
import java.util.LinkedHashMap;
|
import java.util.List;
|
import java.util.Map;
|
|
/**
|
* Intercepts open API calls so they can be audited via IntegrationRecordAdvice.
|
*/
|
@Slf4j
|
@Component
|
public class IntegrationOpenApiInterceptor implements HandlerInterceptor {
|
|
private static final String ATTR_APP_AUTH = "appAuth";
|
private static final String ATTR_AUTH_MEMO = "integrationAuthMemo";
|
private static final String ATTR_CACHE = "cache";
|
private static final String ATTR_START_AT = "openApiStartTime";
|
|
@Override
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
if (!(handler instanceof HandlerMethod)) {
|
return true;
|
}
|
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
IntegrationAuth integrationAuth = findIntegrationAuth(handlerMethod);
|
if (integrationAuth == null) {
|
log.debug("Skip open-api logging for {} because @IntegrationAuth is missing", handlerMethod.getMethod());
|
return true;
|
}
|
|
request.setAttribute(ATTR_APP_AUTH, integrationAuth.value());
|
if (!Cools.isEmpty(integrationAuth.memo())) {
|
request.setAttribute(ATTR_AUTH_MEMO, integrationAuth.memo());
|
}
|
request.setAttribute(ATTR_START_AT, System.currentTimeMillis());
|
request.setAttribute(ATTR_CACHE, buildRequestCache(request));
|
return true;
|
}
|
|
private IntegrationAuth findIntegrationAuth(HandlerMethod handlerMethod) {
|
IntegrationAuth annotation = AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getMethod(), IntegrationAuth.class);
|
if (annotation != null) {
|
return annotation;
|
}
|
return AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBeanType(), IntegrationAuth.class);
|
}
|
|
private Map<String, Object> buildRequestCache(HttpServletRequest request) {
|
Map<String, Object> cache = new LinkedHashMap<>();
|
cache.put("method", request.getMethod());
|
cache.put("uri", request.getRequestURI());
|
cache.put("query", request.getQueryString());
|
cache.put("parameters", flattenParameters(request.getParameterMap()));
|
cache.put("headers", extractHeaders(request));
|
String body = readBody(request);
|
if (!Cools.isEmpty(body)) {
|
cache.put("body", body);
|
}
|
return cache;
|
}
|
|
private Map<String, Object> flattenParameters(Map<String, String[]> rawParams) {
|
Map<String, Object> flattened = new LinkedHashMap<>();
|
if (rawParams == null) {
|
return flattened;
|
}
|
rawParams.forEach((key, values) -> {
|
if (values == null) {
|
flattened.put(key, null);
|
} else if (values.length == 1) {
|
flattened.put(key, values[0]);
|
} else {
|
flattened.put(key, Arrays.asList(values));
|
}
|
});
|
return flattened;
|
}
|
|
private Map<String, Object> extractHeaders(HttpServletRequest request) {
|
Map<String, Object> headers = new LinkedHashMap<>();
|
List<String> names = Collections.list(request.getHeaderNames());
|
for (String name : names) {
|
headers.put(name, request.getHeader(name));
|
}
|
return headers;
|
}
|
|
private String readBody(HttpServletRequest request) {
|
if (request instanceof ContentCachingRequestWrapper) {
|
ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request;
|
byte[] buffer = wrapper.getContentAsByteArray();
|
if (buffer.length > 0) {
|
Charset charset = charset(wrapper.getCharacterEncoding());
|
return new String(buffer, charset);
|
}
|
}
|
return null;
|
}
|
|
private Charset charset(String encoding) {
|
if (Cools.isEmpty(encoding)) {
|
return StandardCharsets.UTF_8;
|
}
|
try {
|
return Charset.forName(encoding);
|
} catch (Exception e) {
|
return StandardCharsets.UTF_8;
|
}
|
}
|
}
|