| | |
| | | package com.zy.acs.manager.common.interceptor; |
| | | |
| | | import com.zy.acs.framework.common.Cools; |
| | | import com.zy.acs.manager.common.annotation.IntegrationAuth; |
| | | import com.zy.acs.manager.core.domain.type.NamespaceType; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | 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.LinkedHashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * Intercepts open API calls so they can be audited via IntegrationRecordAdvice. |
| | |
| | | IntegrationRequestContext context = new IntegrationRequestContext( |
| | | namespaceType, |
| | | handlerMethod.getBeanType().getSimpleName() + "#" + handlerMethod.getMethod().getName(), |
| | | System.currentTimeMillis(), |
| | | buildPayload(request) |
| | | System.currentTimeMillis() |
| | | ); |
| | | request.setAttribute(ATTR_CONTEXT, context); |
| | | return true; |
| | |
| | | return AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBeanType(), IntegrationAuth.class); |
| | | } |
| | | |
| | | private RequestPayload buildPayload(HttpServletRequest request) { |
| | | Map<String, Object> params = flattenParameters(request.getParameterMap()); |
| | | String body = readBody(request); |
| | | return new RequestPayload( |
| | | request.getMethod(), |
| | | request.getRequestURI(), |
| | | request.getQueryString(), |
| | | request.getContentType(), |
| | | params.isEmpty() ? null : params, |
| | | Cools.isEmpty(body) ? null : body |
| | | ); |
| | | } |
| | | |
| | | 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 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; |
| | | } |
| | | } |
| | | |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public static class IntegrationRequestContext { |
| | | |
| | | private IntegrationRequestContext(NamespaceType namespaceType, String handler, long startAt) { |
| | | this.namespaceType = namespaceType; |
| | | this.handler = handler; |
| | | this.startAt = startAt; |
| | | } |
| | | |
| | | private final NamespaceType namespaceType; |
| | | private final String handler; |
| | | private final long startAt; |
| | | private final RequestPayload payload; |
| | | |
| | | } |
| | | |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public static class RequestPayload { |
| | | private final String method; |
| | | private final String uri; |
| | | private final String query; |
| | | private final String contentType; |
| | | private final Map<String, Object> parameters; |
| | | private final String body; |
| | | } |
| | | } |