| package com.suntae.gateway.filter; |
| |
| import com.alibaba.fastjson2.JSON; |
| import com.alibaba.fastjson2.JSONObject; |
| import com.suntae.common.domain.ResultException; |
| import com.suntae.gateway.utils.AESUtils; |
| import io.netty.buffer.ByteBufAllocator; |
| import lombok.extern.slf4j.Slf4j; |
| 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.NettyDataBufferFactory; |
| import org.springframework.http.HttpHeaders; |
| import org.springframework.http.HttpMethod; |
| 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.server.ServerWebExchange; |
| import reactor.core.publisher.Flux; |
| import reactor.core.publisher.Mono; |
| |
| import java.net.URLDecoder; |
| import java.nio.CharBuffer; |
| import java.nio.charset.StandardCharsets; |
| import java.util.LinkedHashMap; |
| import java.util.Map; |
| |
| @Slf4j |
| @Component |
| public class DeCodeGlobalFilter implements GlobalFilter, Ordered { |
| |
| private final static String sk = "aes密钥"; |
| |
| @Override |
| public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { |
| ServerHttpRequest request = exchange.getRequest(); |
| HttpMethod method = request.getMethod(); |
| long contentLength = request.getHeaders().getContentLength(); |
| if (contentLength > 0) { |
| |
| if (HttpMethod.POST.equals(method)) { |
| return handlePostMethod(exchange, request, chain); |
| } |
| } |
| return chain.filter(exchange); |
| } |
| |
| private Mono<Void> handlePostMethod(ServerWebExchange exchange, ServerHttpRequest request, GatewayFilterChain chain) { |
| MediaType contentType = request.getHeaders().getContentType(); |
| if (contentType == null) { |
| return Mono.error(new ResultException("未识别的请求体类型")); |
| } |
| StringBuffer paramBuffer = new StringBuffer(); |
| Flux<DataBuffer> body = exchange.getRequest().getBody(); |
| body.subscribe(buffer -> { |
| |
| CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer()); |
| |
| paramBuffer.append(charBuffer); |
| }); |
| |
| String param = paramBuffer.toString(); |
| JSONObject JsonData = null; |
| if (MediaType.APPLICATION_JSON.isCompatibleWith(contentType)) { |
| JsonData = JSONObject.parseObject(param); |
| } |
| if (MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType)) { |
| JsonData = handleFormURLEncoded(param); |
| } |
| if (MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType)) { |
| JsonData = JSON.parseObject(handleFormData(param, contentType.toString())); |
| } |
| if (JsonData == null) { |
| return Mono.error(new ResultException("不支持的请求体类型")); |
| } |
| |
| for (String str : JsonData.keySet()) { |
| log.info("参数:{}", str); |
| log.info("{}解密前:{}", str, JsonData.get(str)); |
| |
| String enCode = JsonData.getString(str); |
| String deCode; |
| try { |
| deCode = AESUtils.decrypt(URLDecoder.decode(enCode, "UTF-8"), sk); |
| } catch (Exception e) { |
| throw new ResultException("解密失败"); |
| } |
| |
| log.info("{}解密后:{}", str, deCode); |
| param = param.replace(enCode, deCode); |
| } |
| String bodyStr = param; |
| DataBuffer bodyDataBuffer = stringBuffer(bodyStr); |
| Flux<DataBuffer> bodyFlux = Flux.just(bodyDataBuffer); |
| ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator( |
| exchange.getRequest()) { |
| @Override |
| public HttpHeaders getHeaders() { |
| HttpHeaders httpHeaders = new HttpHeaders(); |
| int length = bodyStr.getBytes().length; |
| httpHeaders.putAll(super.getHeaders()); |
| httpHeaders.remove(HttpHeaders.CONTENT_TYPE); |
| httpHeaders.remove(HttpHeaders.CONTENT_LENGTH); |
| httpHeaders.setContentLength(length); |
| httpHeaders.set(HttpHeaders.CONTENT_TYPE, contentType.toString()); |
| |
| return httpHeaders; |
| } |
| |
| @Override |
| public Flux<DataBuffer> getBody() { |
| return bodyFlux; |
| } |
| }; |
| return chain.filter(exchange.mutate().request(mutatedRequest).build()); |
| } |
| |
| private JSONObject handleFormURLEncoded(String param) { |
| |
| |
| JSONObject jsonObject = new JSONObject(); |
| String[] split = param.split("&"); |
| for (String s : split) { |
| String[] split1 = s.split("="); |
| jsonObject.put(split1[0], split1[1]); |
| } |
| return jsonObject; |
| |
| } |
| |
| |
| protected 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; |
| } |
| |
| private String handleFormData(String str, String contentType) { |
| String sep = "--" + contentType.replace("multipart/form-data;boundary=", ""); |
| String[] strs = str.split("\r\n"); |
| boolean bankRow = false; |
| boolean keyRow = true; |
| boolean append = false; |
| Map<String, String> params = new LinkedHashMap<>(); |
| String s = null, key = null; |
| StringBuffer sb = new StringBuffer(); |
| for (int i = 1, len = strs.length - 1; i < len; i++) { |
| s = strs[i]; |
| if (keyRow) { |
| key = s.replace("Content-Disposition: form-data; name=", ""); |
| key = key.substring(1, key.length() - 1); |
| keyRow = false; |
| bankRow = true; |
| sb = new StringBuffer(); |
| append = false; |
| continue; |
| } |
| if (sep.equals(s)) { |
| keyRow = true; |
| if (null != key) { |
| params.put(key, sb.toString()); |
| } |
| append = false; |
| continue; |
| } |
| if (bankRow) { |
| bankRow = false; |
| append = false; |
| continue; |
| } |
| if (append) { |
| sb.append("\r\n"); |
| } |
| sb.append(s); |
| append = true; |
| } |
| if (null != key) { |
| params.put(key, sb.toString()); |
| } |
| return JSON.toJSONString(params); |
| } |
| |
| |
| @Override |
| public int getOrder() { |
| return 1; |
| } |
| } |