|
@@ -0,0 +1,107 @@
|
|
|
|
|
+package space.anyi.openAPIGateway.filter;
|
|
|
|
|
+
|
|
|
|
|
+import org.reactivestreams.Publisher;
|
|
|
|
|
+import org.slf4j.Logger;
|
|
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
|
|
+import org.springframework.cloud.gateway.filter.GatewayFilter;
|
|
|
|
|
+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.HttpHeaders;
|
|
|
|
|
+import org.springframework.http.HttpStatus;
|
|
|
|
|
+import org.springframework.http.server.RequestPath;
|
|
|
|
|
+import org.springframework.http.server.reactive.ServerHttpRequest;
|
|
|
|
|
+import org.springframework.http.server.reactive.ServerHttpResponse;
|
|
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
|
|
+import org.springframework.web.server.ServerWebExchange;
|
|
|
|
|
+import reactor.core.CoreSubscriber;
|
|
|
|
|
+import reactor.core.publisher.Mono;
|
|
|
|
|
+
|
|
|
|
|
+import java.util.HashSet;
|
|
|
|
|
+import java.util.Objects;
|
|
|
|
|
+import java.util.Set;
|
|
|
|
|
+import java.util.function.Function;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * @ProjectName: open-api-gateway
|
|
|
|
|
+ * @FileName: GlobalFilter
|
|
|
|
|
+ * @Author: 杨逸
|
|
|
|
|
+ * @Data:2025/11/20 11:08
|
|
|
|
|
+ * @Description: 局部过滤器
|
|
|
|
|
+ * 只对openAPI接口路由进行过滤处理
|
|
|
|
|
+ */
|
|
|
|
|
+@Component()
|
|
|
|
|
+public class ConsumerFilter implements GlobalFilter, Ordered {
|
|
|
|
|
+ /**
|
|
|
|
|
+ * todo:自定义局部过滤器
|
|
|
|
|
+ * 自定义的过滤器名称规则:后缀一定要是GatewayFilterFactory
|
|
|
|
|
+ * 在配置文件配置自定义过滤器时只需要配置name为Consumer即可
|
|
|
|
|
+ */
|
|
|
|
|
+ public static final Logger log = LoggerFactory.getLogger(ConsumerFilter.class);
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 记录时间戳和随机数nonce(防止重放攻击)
|
|
|
|
|
+ * @see Set<String>
|
|
|
|
|
+ */
|
|
|
|
|
+ public static final Set<String> timestampAndNonceSet = new HashSet<>();
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
|
|
|
|
+ ServerHttpRequest request = exchange.getRequest();
|
|
|
|
|
+ ServerHttpResponse response = exchange.getResponse();
|
|
|
|
|
+ HttpHeaders headers = request.getHeaders();
|
|
|
|
|
+ RequestPath url = request.getPath();
|
|
|
|
|
+ log.debug("url:{}", url);
|
|
|
|
|
+ String accessKey = headers.getFirst("accessKey");
|
|
|
|
|
+ log.debug("accessKey:{}", accessKey);
|
|
|
|
|
+ String timestamp = headers.getFirst("timestamp");
|
|
|
|
|
+ log.debug("timestamp:{}", timestamp);
|
|
|
|
|
+ String sign = headers.getFirst("sign");
|
|
|
|
|
+ log.debug("sign:{}", sign);
|
|
|
|
|
+ String nonce = headers.getFirst("nonce");
|
|
|
|
|
+ log.debug("nonce:{}", nonce);
|
|
|
|
|
+ //校验时间
|
|
|
|
|
+ try {
|
|
|
|
|
+ long five_minutes = 5 * 60 * 1000;
|
|
|
|
|
+ if (Objects.isNull(timestamp) || five_minutes < Math.abs(System.currentTimeMillis() - Long.valueOf(timestamp))) {
|
|
|
|
|
+ log.warn("时间戳{}不合法", timestamp);
|
|
|
|
|
+ return parameterExceptionHandler(response,"时间戳不合法");
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
|
|
+ e.printStackTrace();
|
|
|
|
|
+ log.error("时间戳转换失败",e);
|
|
|
|
|
+ }
|
|
|
|
|
+ //随机数nonce校验
|
|
|
|
|
+ if (Objects.isNull(nonce) || timestampAndNonceSet.contains(timestamp + nonce)) {
|
|
|
|
|
+ log.warn("随机数{}不合法", nonce);
|
|
|
|
|
+ return parameterExceptionHandler(response,"随机数不合法");
|
|
|
|
|
+ }
|
|
|
|
|
+ timestampAndNonceSet.add(timestamp + nonce);
|
|
|
|
|
+ //todo:检查接口是否存在并且开通调用
|
|
|
|
|
+ //todo:是否还有调用次数
|
|
|
|
|
+ //todo:校验accessKey和secretKey
|
|
|
|
|
+
|
|
|
|
|
+ return chain.filter(exchange).then(new Mono<Void>() {
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void subscribe(CoreSubscriber<? super Void> actual) {
|
|
|
|
|
+ //todo:过滤器后置处理
|
|
|
|
|
+ log.info("过滤器后置处理");
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Mono<Void> parameterExceptionHandler(ServerHttpResponse response, String msg) {
|
|
|
|
|
+ response.writeAndFlushWith(new Mono<Publisher<? extends DataBuffer>>() {
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void subscribe(CoreSubscriber<? super Publisher<? extends DataBuffer>> actual) {
|
|
|
|
|
+ actual.onNext(Mono.just(response.bufferFactory().wrap(msg.getBytes())));
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ response.setStatusCode(HttpStatus.BAD_REQUEST);
|
|
|
|
|
+ return response.setComplete();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public int getOrder() {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|