1.首先需求是要对网关通过的所有请求进行解密,客户端进行加密
2.其次gatewaybody不可以进行重复读取,需要存入上下文变量
3.还要打印出具体的接口日志,入参,方式以及出参(解密后的)
- 新建上下文实体
@Data
public class GatewayContext {
public static final String CACHE_GATEWAY_CONTEXT = "cacheGatewayContext";
/**
* cache headers
*/
private HttpHeaders headers;
/**
* cache json body
*/
private String cacheBody;
/**
* cache formdata
*/
private MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
/**
* ipAddress
*/
private String ipAddress;
/**
* path
*/
private String path;
}
- 再建立解密并且存入上下文变量(解密自行实现)
@Slf4j
@Component
public class MyDecryptFilter implements GlobalFilter, Ordered {
private static final List<HttpMessageReader<?>> MESSAGE_READERS = HandlerStrategies.withDefaults().messageReaders();
/**
* 请求头
*/
public static final String HEADER_CONTENT_LENGTH = "Content-Length";
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if (Objects.equals(exchange.getRequest().getMethod(), HttpMethod.POST)) {
ServerRequest serverRequest = ServerRequest.create(exchange, MESSAGE_READERS);
MediaType mediaType = exchange.getRequest().getHeaders().getContentType();
//重点
Mono<String> modifiedBody = serverRequest.bodyToMono(String.class).flatMap(body -> {
// post只考虑json请求验签(其他方式请自行实现)
if (MediaType.APPLICATION_JSON.isCompatibleWith(mediaType) || MediaType.APPLICATION_JSON_UTF8.isCompatibleWith(mediaType)) {
String newBody = "{\"code\":500,\"msg\":\"请求参数签名验证失败!\"}";
try {
JSONObject jsonObject = JSON.parseObject(body);
newBody = verifySign(jsonObject);
} catch (Exception e) {
//do nothing
}
//将验签后的变量存入上下文
putGatewayContext(exchange, newBody);
return Mono.just(newBody);
}
return Mono.empty();
});
BodyInserter<Mono<String>, ReactiveHttpOutputMessage> bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
//获取请求头
HttpHeaders headers = new HttpHeaders();
headers.putAll(exchange.getRequest().getHeaders());
headers.remove(HEADER_CONTENT_LENGTH);
CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
return bodyInserter.insert(outputMessage, new BodyInserterContext()).then(Mono.defer(() -> {
ServerHttpRequest decorator = this.decorate(exchange, headers, outputMessage);
return returnMono(chain, exchange.mutate().request(decorator).build());
}));
} else {
return chain.filter(exchange);
}
}
/**
* 将验签后的json存入上下文,方面调用链下的过滤器获取
*
* @param exchange exchange
*/
private void putGatewayContext(ServerWebExchange exchange, String requestBody) {
ServerHttpRequest request = exchange.getRequest();
HttpHeaders headers = request.getHeaders();
GatewayContext gatewayContext = new GatewayContext();
String path = request.getPath().pathWithinApplication().value();
gatewayContext.setPath(path);
gatewayContext.getFormData().addAll(request.getQueryParams());
gatewayContext.setIpAddress(String.valueOf(request.getRemoteAddress()));
gatewayContext.setHeaders(headers);
gatewayContext.setCacheBody(requestBody);
//将上下文内容存入exchange
exchange.getAttributes().put(GatewayContext.CACHE_GATEWAY_CONTEXT, gatewayContext);
}
/**
* 验证签名
*
* @param jsonObject json对象
* @return 解密后的json字符串
*/
private String verifySign(JSONObject jsonObject) {
//todo 进行验签,然后转为解密后的JSON
return JSON.toJSONString(jsonObject);
}
private Mono<Void> returnMono(GatewayFilterChain chain, ServerWebExchange exchange) {
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
// log.info("状态码:{}", Objects.requireNonNull(exchange.getResponse().getStatusCode()).value());
}));
}
ServerHttpRequestDecorator decorate(ServerWebExchange exchange, HttpHeaders headers, CachedBodyOutputMessage outputMessage) {
return new ServerHttpRequestDecorator(exchange.getRequest()) {
@Override
public HttpHeaders getHeaders() {
long contentLength = headers.getContentLength();
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.putAll(super.getHeaders());
if (contentLength > 0L) {
httpHeaders.setContentLength(contentLength);
} else {
httpHeaders.set("Transfer-Encoding", "chunked");
}
return httpHeaders;
}
@Override
public Flux<DataBuffer> getBody() {
return outputMessage.getBody();
}
};
}
@Override
public int getOrder() {
return -300;
}
}