1.GlobalRequestBodyDecodeFilter.java
package com.itlong.cloud.filters;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
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.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
@Component
@Slf4j
public class GlobalRequestBodyDecodeFilter implements GlobalFilter, Ordered {
@Value("${" + PlatformConstants.GatewayConfig.WEB_SECRET_KEY + "}")
String webSecretKey;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
MediaType contentType = request.getHeaders().getContentType();
String method = request.getMethodValue();
MDC.clear();
if (RequestMethod.POST.name().equals(method)) {
return DataBufferUtils.join(exchange.getRequest().getBody())
.flatMap(dataBuffer -> {
byte[] bytes = new byte[dataBuffer.readableByteCount()];
dataBuffer.read(bytes);
String bodyString = "";
try {
bodyString = new String(bytes, "utf-8");
bodyString = decryptData(contentType, bodyString, exchange);
} catch (UnsupportedEncodingException e) {
log.error("获取请求参数失败!{},{}", ErrorTypeEnum.PARAMETER_ANOMALY, e.getMessage());
}
DataBufferUtils.release(dataBuffer);
String finalBodyString = bodyString;
Flux<DataBuffer> cachedFlux = Flux.defer(() -> {
DataBuffer buffer = exchange.getResponse().bufferFactory()
.wrap(finalBodyString.getBytes(StandardCharsets.UTF_8));
return Mono.just(buffer);
});
ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(
exchange.getRequest()) {
@Override
public Flux<DataBuffer> getBody() {
return cachedFlux;
}
//复写getHeaders方法
@Override
public HttpHeaders getHeaders() {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.putAll(super.getHeaders());
httpHeaders.remove(HttpHeaders.CONTENT_LENGTH);
httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
return httpHeaders;
}
@Override
public URI getURI() {
URI uri = exchange.getRequest().getURI();
URI newUri = UriComponentsBuilder.fromUri(uri)
.build(true)
.toUri();
return newUri;
}
};
return chain.filter(exchange.mutate().request(mutatedRequest)
.build());
});
}
if (RequestMethod.GET.name().equals(method)) {
URI uri = exchange.getRequest().getURI();
String query = "";
String originalQuery = uri.getRawQuery();
if (null != originalQuery && originalQuery.contains(PlatformConstants.GatewayConfig.ENCRYPT_SCRIPT_KEY)) {
try {
//get为url传参 token需要encode
query = getFormData(originalQuery, true, exchange);
} catch (Exception e) {
log.error("get请求解密数据失败!{},{}", ErrorTypeEnum.SYSTEM_ANOMALY, e.getMessage());
}
}
URI newUri = UriComponentsBuilder.fromUri(uri)
.replaceQuery(query)
.build(true)
.toUri();
ServerHttpRequest build = exchange.getRequest().mutate().uri(newUri).build();
return chain.filter(exchange.mutate().request(build).build());
}
return chain.filter(exchange);
}
/**
* 解密数据
*
* @param contentType
* @param bodyJson
* @return
*/
private String decryptData(MediaType contentType, String bodyJson, ServerWebExchange exchange) {
String encryptScript;
String data = "";
try {
if (bodyJson.contains(PlatformConstants.GatewayConfig.ENCRYPT_SCRIPT_KEY)) {
if (MediaType.APPLICATION_JSON.isCompatibleWith(contentType) || MediaType.APPLICATION_JSON_UTF8.isCompatibleWith(contentType)) {
JSONObject json = JSON.parseObject(bodyJson);
encryptScript = json.getString(PlatformConstants.GatewayConfig.ENCRYPT_SCRIPT_KEY);
log.info("encryptScript=======>:{}", encryptScript);
String encryptResult = DesEncryptUtil.aesDecrypt(URLDecoder.decode(encryptScript, "utf-8"), webSecretKey);
json = JSON.parseObject(encryptResult);
log.info("encryptResult=======>:{}", encryptResult);
setRequestId(json, exchange);
exchange.getAttributes().put(PlatformConstants.GatewayConfig.CACHED_REQUEST_BODY, json);
return json.toJSONString();
}
if (MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType)) {
return getFormData(bodyJson, false, exchange);
}
}
} catch (Exception e) {
log.error("请求解密数据失败!{},{}", ErrorTypeEnum.SYSTEM_ANOMALY, e.getMessage());
}
return data;
}
/**
* <desc>
* 设置请求ID
* </desc>
*
* @param json
* @param exchange
* @return void
* @author maju
* @createDate 2021/7/14
*/
private void setRequestId(JSONObject json, ServerWebExchange exchange) {
String requestId = json.getString("requestId");
if (StringUtils.isNotEmpty(requestId)) {
} else {
requestId = IdUtil.fastSimpleUUID();
json.put("addParas", "requestId");
json.put("requestId", requestId);
}
exchange.getAttributes().put(PlatformConstants.Public.REQUEST_ID, requestId);
MDC.put(PlatformConstants.Public.REQUEST_ID, requestId);
}
/**
* 获取form数据
*
* @param bodyJson
* @param isEncode
* @return
* @throws Exception
*/
private String getFormData(String bodyJson, boolean isEncode, ServerWebExchange exchange) throws Exception {
String encryptScript;
encryptScript = bodyJson.split("&")[0].split("=")[1];
log.info("encryptScript=======>:{}", encryptScript);
String encryptResult = DesEncryptUtil.aesDecrypt(URLDecoder.decode(encryptScript, "utf-8"), webSecretKey);
JSONObject json = JSON.parseObject(encryptResult);
setRequestId(json, exchange);
log.info("encryptResult=======>:{}", encryptResult);
StringBuilder sb = new StringBuilder();
json.forEach((k, v) -> {
try {
if (isEncode) {
sb.append(k + "=" + URLEncoder.encode(v.toString(), "utf-8"));
} else {
sb.append(k + "=" + v);
}
} catch (UnsupportedEncodingException e) {
log.error("参数encode异常!{},{}", ErrorTypeEnum.SYSTEM_ANOMALY, e.getMessage());
}
sb.append("&");
});
sb.deleteCharAt(sb.lastIndexOf("&"));
exchange.getAttributes().put(PlatformConstants.GatewayConfig.CACHED_REQUEST_BODY, json);
return sb.toString();
}
@Override
public int getOrder() {
return -200;
}
}
2.GlobalResponseBodyEncodeFilter.java
package com.itlong.cloud.filters;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.reactivestreams.Publisher;
import org.slf4j.MDC;
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.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 对所有的response请求的body进行加密
*/
@Component
@Slf4j
public class GlobalResponseBodyEncodeFilter implements GlobalFilter, Ordered {
@Value("${" + PlatformConstants.GatewayConfig.WEB_SECRET_KEY + "}")
String webSecretKey;
private static Joiner joiner = Joiner.on("");//将 List 数据以""分隔进行拼接
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpResponse originalResponse = exchange.getResponse();
DataBufferFactory bufferFactory = originalResponse.bufferFactory();
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
//设置响应打印请求ID
String requestId = exchange.getAttributeOrDefault(PlatformConstants.Public.REQUEST_ID, "");
MDC.put(PlatformConstants.Public.REQUEST_ID, requestId);
if (body instanceof Flux) {
Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
DataBuffer join = dataBufferFactory.join(dataBuffers);
byte[] content = new byte[join.readableByteCount()];
join.read(content);
DataBufferUtils.release(join);
String result = null;
try {
result = new String(content, Charset.forName("UTF-8"));
} catch (Exception e) {
log.error("获取响应异常!:{},{}", ErrorTypeEnum.SYSTEM_ANOMALY, e.getMessage());
}
// 对响应体进行加密
JSONObject rjson = new JSONObject();
try {
log.info("result==========>:" + result);
//签名且加密
SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
Date date = new Date();
String createTime = df.format(date);
JSONObject json = new JSONObject();
Map<String, Object> jsonToMap = new HashMap<>();
jsonToMap.put("data", result);
String sign = Md5EncryptUtil.cloudDeviceMd5(jsonToMap, createTime, webSecretKey);
json.put("allData", result);
json.put("createTime", createTime);
json.put("sign", sign);
rjson.put("encryptScript", DesEncryptUtil.aesEncryptSDK(json.toJSONString(), webSecretKey));
} catch (Exception e) {
e.printStackTrace();
log.error("加密异常:{},{}", ErrorTypeEnum.SYSTEM_ANOMALY, e.getMessage());
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "响应体加密异常");
}
return bufferFactory.wrap(rjson.toJSONString().getBytes(StandardCharsets.UTF_8));
}));
}
return super.writeWith(body);
}
};
return chain.filter(exchange.mutate().response(decoratedResponse).build());
}
@Override
public int getOrder() {
return -2;
}
}