From 8800476fb84c1e5418b3169836d20e8bc79b47a3 Mon Sep 17 00:00:00 2001 From: liaozan <378024053@qq.com> Date: Sun, 20 Aug 2023 18:55:40 +0800 Subject: [PATCH] Polish request wrapper --- .../web/ServletComponentConfiguration.java | 17 ++++-- .../BodyParamMethodArgumentResolver.java | 10 ++-- .../web/servlet/RequestLoggingFilter.java | 8 +-- .../web/servlet/RequestWrapperFilter.java | 31 +++++++++++ ...bstractSignatureValidationInterceptor.java | 53 +++++++++++-------- .../web/utils/ContentCachingServletUtils.java | 12 +++-- 6 files changed, 93 insertions(+), 38 deletions(-) create mode 100644 commons/web-common/src/main/java/com/schbrain/common/web/servlet/RequestWrapperFilter.java diff --git a/commons/web-common/src/main/java/com/schbrain/common/web/ServletComponentConfiguration.java b/commons/web-common/src/main/java/com/schbrain/common/web/ServletComponentConfiguration.java index 7f10a9f..98b0dd0 100644 --- a/commons/web-common/src/main/java/com/schbrain/common/web/ServletComponentConfiguration.java +++ b/commons/web-common/src/main/java/com/schbrain/common/web/ServletComponentConfiguration.java @@ -3,6 +3,7 @@ package com.schbrain.common.web; import com.schbrain.common.web.properties.WebProperties; import com.schbrain.common.web.servlet.CharacterEncodingServletContextInitializer; import com.schbrain.common.web.servlet.RequestLoggingFilter; +import com.schbrain.common.web.servlet.RequestWrapperFilter; import com.schbrain.common.web.servlet.TraceIdInitializeServletListener; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -20,19 +21,25 @@ public class ServletComponentConfiguration { @Bean @ConditionalOnMissingBean - public TraceIdInitializeServletListener traceIdInitializeServletListener() { + public TraceIdInitializeServletListener defaultTraceIdInitializeServletListener() { return new TraceIdInitializeServletListener(); } @Bean @ConditionalOnMissingBean - public CharacterEncodingServletContextInitializer characterEncodingServletContextInitializer(WebProperties webProperties) { + public CharacterEncodingServletContextInitializer defaultCharacterEncodingServletContextInitializer(WebProperties webProperties) { return new CharacterEncodingServletContextInitializer(webProperties.getEncoding()); } @Bean @ConditionalOnMissingBean - public RequestContextFilter requestContextFilter() { + public RequestWrapperFilter defaukltRequestWrapperFilter() { + return new RequestWrapperFilter(); + } + + @Bean + @ConditionalOnMissingBean + public RequestContextFilter defaultRequestContextFilter() { OrderedRequestContextFilter requestContextFilter = new OrderedRequestContextFilter(); requestContextFilter.setThreadContextInheritable(true); return requestContextFilter; @@ -41,8 +48,8 @@ public class ServletComponentConfiguration { @Bean @ConditionalOnMissingBean @ConditionalOnProperty(value = "schbrain.web.enable-request-logging", havingValue = "true", matchIfMissing = true) - public RequestLoggingFilter requestLoggingFilter() { + public RequestLoggingFilter defaultRequestLoggingFilter() { return new RequestLoggingFilter(); } -} \ No newline at end of file +} diff --git a/commons/web-common/src/main/java/com/schbrain/common/web/argument/BodyParamMethodArgumentResolver.java b/commons/web-common/src/main/java/com/schbrain/common/web/argument/BodyParamMethodArgumentResolver.java index e0e6b14..c2ca55c 100644 --- a/commons/web-common/src/main/java/com/schbrain/common/web/argument/BodyParamMethodArgumentResolver.java +++ b/commons/web-common/src/main/java/com/schbrain/common/web/argument/BodyParamMethodArgumentResolver.java @@ -57,10 +57,10 @@ public class BodyParamMethodArgumentResolver extends AbstractNamedValueMethodArg if (value == null || value.isNull()) { return null; } - return objectMapper.convertValue(value, getJavaType(parameter)); + return objectMapper.convertValue(value, toJavaType(parameter)); } - private JavaType getJavaType(MethodParameter parameter) { + private JavaType toJavaType(MethodParameter parameter) { Type parameterType = parameter.getNestedGenericParameterType(); return objectMapper.constructType(parameterType); } @@ -68,11 +68,15 @@ public class BodyParamMethodArgumentResolver extends AbstractNamedValueMethodArg private JsonNode getRequestBody(NativeWebRequest nativeWebRequest) throws IOException { JsonNode requestBody = (JsonNode) nativeWebRequest.getAttribute(REQUEST_BODY_CACHE, SCOPE_REQUEST); if (requestBody == null) { - ContentCachingRequestWrapper request = wrapRequestIfRequired(nativeWebRequest.getNativeRequest(HttpServletRequest.class)); + ContentCachingRequestWrapper request = wrapRequest(nativeWebRequest); requestBody = objectMapper.readTree(request.getInputStream()); nativeWebRequest.setAttribute(REQUEST_BODY_CACHE, requestBody, SCOPE_REQUEST); } return requestBody; } + private ContentCachingRequestWrapper wrapRequest(NativeWebRequest nativeWebRequest) { + return wrapRequestIfRequired(nativeWebRequest.getNativeRequest(HttpServletRequest.class)); + } + } diff --git a/commons/web-common/src/main/java/com/schbrain/common/web/servlet/RequestLoggingFilter.java b/commons/web-common/src/main/java/com/schbrain/common/web/servlet/RequestLoggingFilter.java index 0fa7f3f..1b599f7 100644 --- a/commons/web-common/src/main/java/com/schbrain/common/web/servlet/RequestLoggingFilter.java +++ b/commons/web-common/src/main/java/com/schbrain/common/web/servlet/RequestLoggingFilter.java @@ -1,7 +1,6 @@ package com.schbrain.common.web.servlet; import cn.hutool.core.text.CharPool; -import com.schbrain.common.web.utils.ContentCachingServletUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.boot.web.servlet.filter.OrderedFilter; @@ -15,6 +14,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import static com.schbrain.common.web.utils.ContentCachingServletUtils.getRequestBody; import static com.schbrain.common.web.utils.ContentCachingServletUtils.wrapRequestIfRequired; /** @@ -55,14 +55,14 @@ public class RequestLoggingFilter extends OncePerRequestFilter implements Ordere String method = request.getMethod(); String requestUri = request.getRequestURI(); String queryString = request.getQueryString(); - String body = ContentCachingServletUtils.getRequestBody(request, false); + String requestBody = getRequestBody(request, false); StringBuilder builder = new StringBuilder(); builder.append("requestUri: ").append(method).append(CharPool.SPACE).append(requestUri); if (StringUtils.isNotBlank(queryString)) { builder.append(", queryString: ").append(queryString); } - if (StringUtils.isNotBlank(body)) { - builder.append(", body: ").append(body); + if (StringUtils.isNotBlank(requestBody)) { + builder.append(", body: ").append(requestBody); } builder.append(", startTime: ").append(startTime); builder.append(", endTime: ").append(endTime); diff --git a/commons/web-common/src/main/java/com/schbrain/common/web/servlet/RequestWrapperFilter.java b/commons/web-common/src/main/java/com/schbrain/common/web/servlet/RequestWrapperFilter.java new file mode 100644 index 0000000..ceb1b29 --- /dev/null +++ b/commons/web-common/src/main/java/com/schbrain/common/web/servlet/RequestWrapperFilter.java @@ -0,0 +1,31 @@ +package com.schbrain.common.web.servlet; + +import org.springframework.boot.web.servlet.filter.OrderedFilter; +import org.springframework.core.Ordered; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +import static com.schbrain.common.web.utils.ContentCachingServletUtils.wrapRequestIfRequired; + +/** + * @author liaozan + * @since 2023/8/20 + */ +public class RequestWrapperFilter extends OncePerRequestFilter implements OrderedFilter { + + @Override + public int getOrder() { + return Ordered.HIGHEST_PRECEDENCE; + } + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { + chain.doFilter(wrapRequestIfRequired(request), response); + } + +} diff --git a/commons/web-common/src/main/java/com/schbrain/common/web/support/signature/AbstractSignatureValidationInterceptor.java b/commons/web-common/src/main/java/com/schbrain/common/web/support/signature/AbstractSignatureValidationInterceptor.java index 220770d..51e6bf1 100644 --- a/commons/web-common/src/main/java/com/schbrain/common/web/support/signature/AbstractSignatureValidationInterceptor.java +++ b/commons/web-common/src/main/java/com/schbrain/common/web/support/signature/AbstractSignatureValidationInterceptor.java @@ -1,30 +1,36 @@ package com.schbrain.common.web.support.signature; import cn.hutool.crypto.digest.DigestUtil; +import com.google.common.base.Joiner; import com.schbrain.common.web.support.BaseHandlerInterceptor; import org.apache.commons.lang3.StringUtils; import org.springframework.web.method.HandlerMethod; +import org.springframework.web.util.ContentCachingRequestWrapper; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.util.Objects; import static cn.hutool.core.text.StrPool.UNDERLINE; import static com.schbrain.common.web.utils.ContentCachingServletUtils.getRequestBody; -import static com.schbrain.common.web.utils.ContentCachingServletUtils.wrapRequestIfRequired; +import static org.springframework.web.util.WebUtils.getNativeRequest; public abstract class AbstractSignatureValidationInterceptor extends BaseHandlerInterceptor { + private static final Joiner JOINER = Joiner.on(UNDERLINE).skipNulls(); + private static final String SCH_APP_KEY = "Sch-App-Key"; private static final String SCH_TIMESTAMP = "Sch-Timestamp"; private static final String SCH_SIGNATURE = "Sch-Signature"; private static final String SCH_EXPIRE_TIME = "Sch-Expire-Time"; @Override - protected boolean preHandle(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) { - String appKey = request.getHeader(SCH_APP_KEY); - String timestamp = request.getHeader(SCH_TIMESTAMP); - String signature = request.getHeader(SCH_SIGNATURE); - String expireTime = request.getHeader(SCH_EXPIRE_TIME); + protected boolean preHandle(HttpServletRequest request, HttpServletResponse response, HandlerMethod handler) { + ContentCachingRequestWrapper wrappedRequest = getWrappedRequest(request); + + String appKey = wrappedRequest.getHeader(SCH_APP_KEY); + String timestamp = wrappedRequest.getHeader(SCH_TIMESTAMP); + String signature = wrappedRequest.getHeader(SCH_SIGNATURE); // 空校验 if (StringUtils.isAnyBlank(appKey, timestamp, signature)) { @@ -32,6 +38,7 @@ public abstract class AbstractSignatureValidationInterceptor Long.parseLong(expireTime)) { throw new SignatureValidationException("请求信息已过期!"); } @@ -39,16 +46,16 @@ public abstract class AbstractSignatureValidationInterceptor