mirror of
https://gitee.com/dromara/RuoYi-Cloud-Plus.git
synced 2025-09-03 02:56:09 +00:00
update 优化 gateway filter顺序 与 代码工具封装
This commit is contained in:
@@ -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<Void> 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;
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
|
||||
/**
|
||||
* 全局日志过滤器
|
||||
* <p>
|
||||
@@ -43,16 +33,16 @@ public class GlobalLogFilter implements GlobalFilter, Ordered {
|
||||
|
||||
@Override
|
||||
public Mono<Void> 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<String, String> 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<DataBuffer> 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<URI> uris = exchange.getRequiredAttribute(GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
|
||||
URI requestUri = uris.stream().findFirst().orElse(request.getURI());
|
||||
return UriComponentsBuilder.fromPath(requestUri.getRawPath()).build().toUriString();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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<Object> {
|
||||
}
|
||||
|
||||
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<Object> {
|
||||
};
|
||||
}
|
||||
|
||||
private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) {
|
||||
// 获取请求体
|
||||
Flux<DataBuffer> body = serverHttpRequest.getBody();
|
||||
AtomicReference<String> bodyRef = new AtomicReference<>();
|
||||
body.subscribe(buffer -> {
|
||||
CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
|
||||
DataBufferUtils.release(buffer);
|
||||
bodyRef.set(charBuffer.toString());
|
||||
});
|
||||
return bodyRef.get();
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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<URI> 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<DataBuffer> body = serverHttpRequest.getBody();
|
||||
AtomicReference<String> 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模型响应
|
||||
*
|
||||
|
Reference in New Issue
Block a user