|
@@ -0,0 +1,127 @@
|
|
|
+package com.huimv.gateway.filter;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.huimv.gateway.utils.JdkSignatureUtil;
|
|
|
+import io.netty.buffer.ByteBufAllocator;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+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.core.io.buffer.DataBufferUtils;
|
|
|
+import org.springframework.core.io.buffer.NettyDataBufferFactory;
|
|
|
+import org.springframework.http.HttpStatus;
|
|
|
+import org.springframework.http.server.reactive.ServerHttpRequest;
|
|
|
+import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
|
|
|
+import org.springframework.http.server.reactive.ServerHttpResponse;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+import org.springframework.web.server.ServerWebExchange;
|
|
|
+import reactor.core.publisher.Flux;
|
|
|
+import reactor.core.publisher.Mono;
|
|
|
+
|
|
|
+import java.net.URI;
|
|
|
+import java.net.URLDecoder;
|
|
|
+import java.nio.CharBuffer;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+
|
|
|
+import java.util.Comparator;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.concurrent.atomic.AtomicReference;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @Author yinhao
|
|
|
+ * @Date 2021/5/6 9:26
|
|
|
+ * @Description
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Component
|
|
|
+public class SignVerifyFilter implements GlobalFilter, Ordered {
|
|
|
+
|
|
|
+ @Value("${huimv.public-key}")
|
|
|
+ private String PUBLIC_KEY;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
|
|
+
|
|
|
+ ServerHttpRequest serverHttpRequest = exchange.getRequest();
|
|
|
+ ServerHttpResponse response = exchange.getResponse();
|
|
|
+ String method = serverHttpRequest.getMethodValue();
|
|
|
+ if ("POST".equals(method)) {
|
|
|
+ //从请求里获取Post请求体
|
|
|
+ String bodyStr = resolveBodyFromRequest(serverHttpRequest);
|
|
|
+ //TODO 得到Post请求的请求参数后,做你想做的事
|
|
|
+ JSONObject jsonObject = JSONObject.parseObject(bodyStr);
|
|
|
+ String sign = jsonObject.getString("sign");
|
|
|
+ try {
|
|
|
+ String decode = URLDecoder.decode(sign, "UTF-8");
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
+ jsonObject.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getKey)).forEach(entry ->
|
|
|
+ sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&"));
|
|
|
+ String paramStr = sb.toString().substring(0, sb.length() - 1);
|
|
|
+ boolean result = JdkSignatureUtil.verifySignature(PUBLIC_KEY,decode,paramStr);
|
|
|
+ if (!result) {
|
|
|
+ response.setStatusCode(HttpStatus.FORBIDDEN);
|
|
|
+ return response.setComplete();
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //下面的将请求体再次封装写回到request里,传到下一级,否则,由于请求体已被消费,后续的服务将取不到值
|
|
|
+ URI uri = serverHttpRequest.getURI();
|
|
|
+ ServerHttpRequest request = serverHttpRequest.mutate().uri(uri).build();
|
|
|
+ DataBuffer bodyDataBuffer = stringBuffer(bodyStr);
|
|
|
+ Flux<DataBuffer> bodyFlux = Flux.just(bodyDataBuffer);
|
|
|
+
|
|
|
+ request = new ServerHttpRequestDecorator(request) {
|
|
|
+ @Override
|
|
|
+ public Flux<DataBuffer> getBody() {
|
|
|
+ return bodyFlux;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ //封装request,传给下一级
|
|
|
+ return chain.filter(exchange.mutate().request(request).build());
|
|
|
+ } else if ("GET".equals(method)) {
|
|
|
+ Map requestQueryParams = serverHttpRequest.getQueryParams();
|
|
|
+ //TODO 得到Get请求的请求参数后,做你想做的事
|
|
|
+
|
|
|
+ return chain.filter(exchange);
|
|
|
+ }
|
|
|
+ return chain.filter(exchange);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从Flux<DataBuffer>中获取字符串的方法
|
|
|
+ *
|
|
|
+ * @return 请求体
|
|
|
+ */
|
|
|
+ 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());
|
|
|
+ });
|
|
|
+ //获取request body
|
|
|
+ return bodyRef.get();
|
|
|
+ }
|
|
|
+
|
|
|
+ private DataBuffer stringBuffer(String value) {
|
|
|
+ byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
|
|
|
+
|
|
|
+ NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
|
|
|
+ DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length);
|
|
|
+ buffer.write(bytes);
|
|
|
+ return buffer;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int getOrder() {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+}
|