|
|
@@ -0,0 +1,121 @@
|
|
|
+package com.kxs.gateway.api.filter;
|
|
|
+
|
|
|
+import cn.hutool.core.text.CharSequenceUtil;
|
|
|
+import cn.hutool.crypto.symmetric.AES;
|
|
|
+import com.kxs.common.core.constant.enums.ErrorTypeEnum;
|
|
|
+import com.kxs.common.core.exception.AesDecodeException;
|
|
|
+import com.kxs.common.core.exception.CheckedException;
|
|
|
+import com.kxs.common.core.exception.ValidateCodeException;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.cloud.gateway.filter.GatewayFilter;
|
|
|
+import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
|
|
|
+import org.springframework.cloud.gateway.filter.factory.rewrite.CachedBodyOutputMessage;
|
|
|
+import org.springframework.cloud.gateway.support.BodyInserterContext;
|
|
|
+import org.springframework.core.io.buffer.DataBuffer;
|
|
|
+import org.springframework.http.HttpHeaders;
|
|
|
+import org.springframework.http.HttpMethod;
|
|
|
+import org.springframework.http.ReactiveHttpOutputMessage;
|
|
|
+import org.springframework.http.server.reactive.ServerHttpRequest;
|
|
|
+import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
|
|
|
+import org.springframework.web.reactive.function.BodyInserter;
|
|
|
+import org.springframework.web.reactive.function.BodyInserters;
|
|
|
+import org.springframework.web.reactive.function.server.HandlerStrategies;
|
|
|
+import org.springframework.web.reactive.function.server.ServerRequest;
|
|
|
+import org.springframework.web.server.ServerWebExchange;
|
|
|
+import reactor.core.publisher.Flux;
|
|
|
+import reactor.core.publisher.Mono;
|
|
|
+
|
|
|
+import java.lang.reflect.Field;
|
|
|
+import java.net.URI;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author lengleng
|
|
|
+ * @date 2019 /2/1 密码解密工具类
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@RequiredArgsConstructor
|
|
|
+public class RequestDecoderFilter extends AbstractGatewayFilterFactory<Object> {
|
|
|
+
|
|
|
+ private final AES cryptoAes;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public GatewayFilter apply(Object config) {
|
|
|
+ return (exchange, chain) -> {
|
|
|
+ ServerHttpRequest request = exchange.getRequest();
|
|
|
+ //请求方法
|
|
|
+ HttpMethod method = request.getMethod();
|
|
|
+
|
|
|
+ if (method == HttpMethod.GET) {
|
|
|
+ //1 修改请求参数,并获取请求参数
|
|
|
+ try {
|
|
|
+ updateRequestParam(exchange);
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new CheckedException("解密异常");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (method != HttpMethod.POST) {
|
|
|
+ return chain.filter(exchange);
|
|
|
+ }
|
|
|
+ //2 获取请求体,修改请求体
|
|
|
+ ServerRequest serverRequest = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders());
|
|
|
+
|
|
|
+ Mono<String> modifiedBody = serverRequest.bodyToMono(String.class).flatMap(body -> {
|
|
|
+ //解密请求体
|
|
|
+ try {
|
|
|
+ log.info("Post请求:{},待解密请求参数:{}", request.getURI().getPath(), body);
|
|
|
+ String encrypt = cryptoAes.decryptStr(body);
|
|
|
+
|
|
|
+ return Mono.just(encrypt);
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error(ErrorTypeEnum.DECRYPT_ERROR.getDescription(), e);
|
|
|
+ return Mono.error(new AesDecodeException(ErrorTypeEnum.DECRYPT_ERROR.getDescription()));
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ //3 创建BodyInserter修改请求体
|
|
|
+ BodyInserter<Mono<String>, ReactiveHttpOutputMessage> bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
+ headers.putAll(exchange.getRequest().getHeaders());
|
|
|
+ headers.remove(HttpHeaders.CONTENT_LENGTH);
|
|
|
+ //4 创建CachedBodyOutputMessage并且把请求param加入
|
|
|
+ CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
|
|
|
+ return bodyInserter.insert(outputMessage, new BodyInserterContext()).then(Mono.defer(() -> {
|
|
|
+ ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(exchange.getRequest()) {
|
|
|
+ @Override
|
|
|
+ public Flux<DataBuffer> getBody() {
|
|
|
+ return outputMessage.getBody();
|
|
|
+ }
|
|
|
+ };
|
|
|
+ return chain.filter(exchange.mutate().request(decorator).build());
|
|
|
+ }));
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 修改前端传的参数
|
|
|
+ */
|
|
|
+ private void updateRequestParam(ServerWebExchange exchange) throws NoSuchFieldException, IllegalAccessException {
|
|
|
+ ServerHttpRequest request = exchange.getRequest();
|
|
|
+ //请求链接
|
|
|
+ URI uri = request.getURI();
|
|
|
+ //请求参数
|
|
|
+ String value = request.getQueryParams().getFirst("value");
|
|
|
+ log.info("Get请求:{},待解密请求参数:{}", uri.getPath(), value);
|
|
|
+ //判断是否有加密的参数 这里的约定是 param
|
|
|
+ if (CharSequenceUtil.isNotBlank(value)) {
|
|
|
+ //解密请求参数
|
|
|
+ String decryPtoData = cryptoAes.decryptStr(value);
|
|
|
+ log.info("Get请求:{},解密之后参数:{}", uri.getPath(), decryPtoData);
|
|
|
+ //使用反射强行拿出 URI 的 query
|
|
|
+ Field targetQuery = uri.getClass().getDeclaredField("value");
|
|
|
+ //授权
|
|
|
+ targetQuery.setAccessible(true);
|
|
|
+ //重新设置参数
|
|
|
+ targetQuery.set(uri, decryPtoData);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|