diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/GlobalCacheRequestFilter.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/GlobalCacheRequestFilter.java index 1e9736df..99c69a8e 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/GlobalCacheRequestFilter.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/GlobalCacheRequestFilter.java @@ -1,10 +1,10 @@ package com.ruoyi.gateway.filter; +import com.ruoyi.gateway.utils.WebFluxUtils; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.cloud.gateway.support.ServerWebExchangeUtils; import org.springframework.core.Ordered; -import org.springframework.http.HttpMethod; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; @@ -19,9 +19,8 @@ public class GlobalCacheRequestFilter implements GlobalFilter, Ordered { @Override public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { - // GET DELETE 不过滤 - HttpMethod method = exchange.getRequest().getMethod(); - if (method == null || method == HttpMethod.GET || method == HttpMethod.DELETE) { + // 只缓存json类型请求 + if (!WebFluxUtils.isJsonRequest(exchange)) { return chain.filter(exchange); } return ServerWebExchangeUtils.cacheRequestBody(exchange, (serverHttpRequest) -> { @@ -34,6 +33,6 @@ public class GlobalCacheRequestFilter implements GlobalFilter, Ordered { @Override public int getOrder() { - return 0; + return Ordered.HIGHEST_PRECEDENCE; } } diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/GlobalLogFilter.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/GlobalLogFilter.java index 7b697ee6..f450cfcc 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/GlobalLogFilter.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/GlobalLogFilter.java @@ -2,29 +2,19 @@ package com.ruoyi.gateway.filter; import cn.hutool.core.map.MapUtil; import com.ruoyi.common.core.utils.JsonUtils; -import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.gateway.config.properties.CustomGatewayProperties; +import com.ruoyi.gateway.utils.WebFluxUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.http.MediaType; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.stereotype.Component; import org.springframework.util.MultiValueMap; import org.springframework.web.server.ServerWebExchange; -import org.springframework.web.util.UriComponentsBuilder; -import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.LinkedHashSet; - -import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR; - /** * 全局日志过滤器 *

@@ -43,16 +33,16 @@ public class GlobalLogFilter implements GlobalFilter, Ordered { @Override public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { - ServerHttpRequest request = exchange.getRequest(); - String path = getOriginalRequestUrl(exchange); - String url = request.getMethod().name() + " " + path; - if (!customGatewayProperties.getRequestLog()) { return chain.filter(exchange); } + ServerHttpRequest request = exchange.getRequest(); + String path = WebFluxUtils.getOriginalRequestUrl(exchange); + String url = request.getMethod().name() + " " + path; + // 打印请求参数 - if (isJsonRequest(request)) { - String jsonParam = resolveBodyFromRequest(request); + if (WebFluxUtils.isJsonRequest(exchange)) { + String jsonParam = WebFluxUtils.resolveBodyFromCacheRequest(exchange); log.debug("[PLUS]开始请求 => URL[{}],参数类型[json],参数:[{}]", url, jsonParam); } else { MultiValueMap parameterMap = request.getQueryParams(); @@ -79,38 +69,4 @@ public class GlobalLogFilter implements GlobalFilter, Ordered { return Ordered.LOWEST_PRECEDENCE; } - /** - * 判断本次请求的数据类型是否为json - * - * @param request request - * @return boolean - */ - private boolean isJsonRequest(ServerHttpRequest request) { - MediaType contentType = request.getHeaders().getContentType(); - if (contentType != null) { - return StringUtils.startsWithIgnoreCase(contentType.toString(), MediaType.APPLICATION_JSON_VALUE); - } - return false; - } - - private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) { - //获取请求体 - Flux body = serverHttpRequest.getBody(); - StringBuilder sb = new StringBuilder(); - body.subscribe(buffer -> { - byte[] bytes = new byte[buffer.readableByteCount()]; - buffer.read(bytes); - String bodyString = new String(bytes, StandardCharsets.UTF_8); - sb.append(bodyString); - }); - return sb.toString(); - } - - public static String getOriginalRequestUrl(ServerWebExchange exchange) { - ServerHttpRequest request = exchange.getRequest(); - LinkedHashSet uris = exchange.getRequiredAttribute(GATEWAY_ORIGINAL_REQUEST_URL_ATTR); - URI requestUri = uris.stream().findFirst().orElse(request.getURI()); - return UriComponentsBuilder.fromPath(requestUri.getRawPath()).build().toUriString(); - } - } diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/ValidateCodeFilter.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/ValidateCodeFilter.java index 40877278..2ec3cafe 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/ValidateCodeFilter.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/ValidateCodeFilter.java @@ -9,15 +9,8 @@ import com.ruoyi.gateway.utils.WebFluxUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.stereotype.Component; -import reactor.core.publisher.Flux; - -import java.nio.CharBuffer; -import java.nio.charset.StandardCharsets; -import java.util.concurrent.atomic.AtomicReference; /** * 验证码过滤器 @@ -49,7 +42,7 @@ public class ValidateCodeFilter extends AbstractGatewayFilterFactory { } try { - String rspStr = resolveBodyFromRequest(request); + String rspStr = WebFluxUtils.resolveBodyFromCacheRequest(exchange); Dict obj = JsonUtils.parseMap(rspStr); validateCodeService.checkCaptcha(obj.getStr(CODE), obj.getStr(UUID)); } catch (Exception e) { @@ -59,15 +52,4 @@ public class ValidateCodeFilter extends AbstractGatewayFilterFactory { }; } - private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) { - // 获取请求体 - Flux body = serverHttpRequest.getBody(); - AtomicReference bodyRef = new AtomicReference<>(); - body.subscribe(buffer -> { - CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer()); - DataBufferUtils.release(buffer); - bodyRef.set(charBuffer.toString()); - }); - return bodyRef.get(); - } } diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/XssFilter.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/XssFilter.java index c328230a..f1162bc9 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/XssFilter.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/XssFilter.java @@ -3,6 +3,7 @@ package com.ruoyi.gateway.filter; import cn.hutool.http.HtmlUtil; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.gateway.config.properties.XssProperties; +import com.ruoyi.gateway.utils.WebFluxUtils; import io.netty.buffer.ByteBufAllocator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -12,7 +13,6 @@ import org.springframework.core.Ordered; import org.springframework.core.io.buffer.*; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpRequestDecorator; import org.springframework.stereotype.Component; @@ -43,7 +43,7 @@ public class XssFilter implements GlobalFilter, Ordered { return chain.filter(exchange); } // 非json类型,不过滤 - if (!isJsonRequest(exchange)) { + if (!WebFluxUtils.isJsonRequest(exchange)) { return chain.filter(exchange); } // excludeUrls 不过滤 @@ -93,16 +93,6 @@ public class XssFilter implements GlobalFilter, Ordered { return serverHttpRequestDecorator; } - /** - * 是否是Json请求 - * - * @param exchange HTTP请求 - */ - public boolean isJsonRequest(ServerWebExchange exchange) { - String header = exchange.getRequest().getHeaders().getFirst(HttpHeaders.CONTENT_TYPE); - return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE); - } - @Override public int getOrder() { return -100; diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/utils/WebFluxUtils.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/utils/WebFluxUtils.java index 2de11e5c..2d06873b 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/utils/WebFluxUtils.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/utils/WebFluxUtils.java @@ -2,13 +2,30 @@ package com.ruoyi.gateway.utils; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.utils.JsonUtils; +import com.ruoyi.common.core.utils.StringUtils; +import com.ruoyi.gateway.filter.GlobalCacheRequestFilter; +import org.springframework.cloud.gateway.support.ServerWebExchangeUtils; import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; +import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.util.UriComponentsBuilder; +import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; +import java.net.URI; +import java.nio.CharBuffer; +import java.nio.charset.StandardCharsets; +import java.util.LinkedHashSet; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; + +import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR; + /** * WebFlux 工具类 * @@ -16,6 +33,57 @@ import reactor.core.publisher.Mono; */ public class WebFluxUtils { + /** + * 获取原请求路径 + */ + public static String getOriginalRequestUrl(ServerWebExchange exchange) { + ServerHttpRequest request = exchange.getRequest(); + LinkedHashSet uris = exchange.getRequiredAttribute(GATEWAY_ORIGINAL_REQUEST_URL_ATTR); + URI requestUri = uris.stream().findFirst().orElse(request.getURI()); + return UriComponentsBuilder.fromPath(requestUri.getRawPath()).build().toUriString(); + } + + /** + * 是否是Json请求 + * + * @param exchange HTTP请求 + */ + public static boolean isJsonRequest(ServerWebExchange exchange) { + String header = exchange.getRequest().getHeaders().getFirst(HttpHeaders.CONTENT_TYPE); + return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE); + } + + /** + * 读取request内的body + * + * 注意一个request只能读取一次 读取之后需要重新包装 + */ + public static String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) { + // 获取请求体 + Flux body = serverHttpRequest.getBody(); + AtomicReference bodyRef = new AtomicReference<>(); + body.subscribe(buffer -> { + CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer()); + DataBufferUtils.release(buffer); + bodyRef.set(charBuffer.toString()); + }); + return bodyRef.get(); + } + + /** + * 从缓存中读取request内的body + * + * 注意要求经过 {@link ServerWebExchangeUtils#cacheRequestBody(ServerWebExchange, Function)} 此方法创建缓存 + * 框架内已经使用 {@link GlobalCacheRequestFilter} 全局创建了body缓存 + * + * @return body + */ + public static String resolveBodyFromCacheRequest(ServerWebExchange exchange) { + DataBuffer buffer = (DataBuffer) exchange.getAttributes().get(ServerWebExchangeUtils.CACHED_REQUEST_BODY_ATTR); + CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer()); + return charBuffer.toString(); + } + /** * 设置webflux模型响应 *