zoukankan      html  css  js  c++  java
  • Spring Cloud网关使用GlobalFilter过滤器做参数加密传输

    package com.lll.serviceingateway.sso;
    
    import com.alibaba.fastjson.JSONObject;
    import com.lll.serviceingateway.sso.util.AESUtil;
    import com.lll.serviceingateway.sso.util.Sm4Util;
    import io.netty.buffer.ByteBufAllocator;
    import lombok.SneakyThrows;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    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.HttpMethod;
    import org.springframework.http.server.reactive.ServerHttpRequest;
    import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
    import org.springframework.stereotype.Component;
    import org.springframework.util.MultiValueMap;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Flux;
    import reactor.core.publisher.Mono;
    
    import java.net.URI;
    import java.nio.CharBuffer;
    import java.nio.charset.StandardCharsets;
    import java.util.Base64;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.concurrent.atomic.AtomicReference;
    
    /**
     * 参数加密传输
     *
     * @author: lll
     * @date: 2021年08月27日 14:08:20
     */
    @Component
    public class ParamsEncryptionFilter implements GlobalFilter, Ordered {
    
    
        static Logger logger = LoggerFactory.getLogger(ParamsEncryptionFilter.class);
    
        @SneakyThrows
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            ServerHttpRequest serverHttpRequest = exchange.getRequest();
            HttpMethod method = serverHttpRequest.getMethod();
            String encryptionType = serverHttpRequest.getHeaders().getFirst("encryptionType");
            URI uri = serverHttpRequest.getURI();
            if (encryptionType != null) {
                if (method == HttpMethod.POST || method == HttpMethod.PUT) {
                    //从请求里获取Post请求体
                    String bodyStr = resolveBodyFromRequest(serverHttpRequest);
                    logger.info("PUT OR POST bodyStr: " + bodyStr);
                    if (bodyStr != null) {
                        JSONObject bodyJson = JSONObject.parseObject(bodyStr);
                        String paramsStr = bodyJson.getString("params");
                        //解密
                        logger.info("PUT OR POST ciphertext  parameters: " + paramsStr);
                        paramsStr = decodeParamsBytype(encryptionType, paramsStr);
                        //非法非法加密处理,不进行解密操作
                        if ("-1".equals(paramsStr)) {
                            return chain.filter(exchange);
                        }
                        logger.info("PUT OR POST plaintext parameters: " + paramsStr);
    
                        //封装request,传给下一级
                        ServerHttpRequest request = serverHttpRequest.mutate().uri(uri).build();
                        DataBuffer bodyDataBuffer = stringBuffer(paramsStr);
                        Flux<DataBuffer> bodyFlux = Flux.just(bodyDataBuffer);
                        request = new ServerHttpRequestDecorator(request) {
                            @Override
                            public Flux<DataBuffer> getBody() {
                                return bodyFlux;
                            }
                        };
                        return chain.filter(exchange.mutate().request(request).build());
                    }
                } else if (method == HttpMethod.GET || method == HttpMethod.DELETE) {
                    try {
                        MultiValueMap<String, String> requestQueryParams = serverHttpRequest.getQueryParams();
                        logger.info("GET OR DELETE ciphertext  parameters: " + requestQueryParams.get("params").get(0));
                        String params = requestQueryParams.get("params").get(0);
                        //解密
                        params = decodeParamsBytype(encryptionType, params);
                        //非法非法加密处理,不进行解密操作
                        if ("-1".equals(params)) {
                            return chain.filter(exchange);
                        }
                        logger.info("GET OR DELETE plaintext parameters: " + params);
                        // 封装URL
                        URI plaintUrl = new URI(uri.getScheme(), uri.getAuthority(),
                                uri.getPath(), params, uri.getFragment());
                        //封装request,传给下一级
                        ServerHttpRequest request = serverHttpRequest.mutate().uri(plaintUrl).build();
                        logger.info("get OR delete plaintext request.getQueryParams(): " + request.getQueryParams());
                        return chain.filter(exchange.mutate().request(request).build());
                    } catch (Exception e) {
                        return chain.filter(exchange);
                    }
                }
            }
            return chain.filter(exchange);
    
        }
    
        /**
         * 解密过滤器必须在所有过滤器之前,否后后续过滤器获取参数会报错
         * 如果有的其他的过滤器添加请调整过滤器顺序
         */
        @Override
        public int getOrder() {
         // 这个排序只能给否则get请求修改的参数不生效
    return -2; } //根据类型进行解密 private String decodeParamsBytype(String type, String params) throws Exception { if ("BA".equals(type)) { //BASE64解密 return new String(Base64.getDecoder().decode(params)); } else if ("AE".equals(type)) { //AES128解密 return AESUtil.aesDecrypt(params); } else if ("SM".equals(type)) { //SM4解密 return Sm4Util.decryptEcb(params); } else { //非法解密 return "-1"; } } 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; } /** * 解析出url参数中的键值对 * 如 "Action=del&id=123",解析出Action:del,id:123存入map中 * * @param params url地址 * @return url请求参数部分 */ private static Map<String, String> urlSplit(String params) { Map<String, String> mapRequest = new HashMap<>(); String[] arrSplit = null; if (params == null) { return mapRequest; } arrSplit = params.split("[&]"); for (String strSplit : arrSplit) { String[] arrSplitEqual = null; arrSplitEqual = strSplit.split("[=]"); //解析出键值 if (arrSplitEqual.length > 1) { //正确解析 mapRequest.put(arrSplitEqual[0], arrSplitEqual[1]); } else if (arrSplitEqual[0] != "") { //只有参数没有值,不加入 mapRequest.put(arrSplitEqual[0], ""); } } return mapRequest; } public static void main(String[] args) throws Exception { String params = "{"pageSize":10,"pageNo":1,"mlmc":"","lmId":"02020072909122290800000101001101","gxzq":[],"mlzt":[],"kflx":[],"zylx":[]}"; //base64 String encodeParams = Base64.getEncoder().encodeToString(params.getBytes()); logger.info("BASE64 encodeParams: " + encodeParams); String decoderParams = new String(Base64.getDecoder().decode(encodeParams)); logger.info("BASE64 decoderParams: " + decoderParams); //aes128 String aesEncodeParams = AESUtil.aesEncrypt(params); logger.info("aesEncodeParams: " + aesEncodeParams); String aesdecodeParams = AESUtil.aesDecrypt(aesEncodeParams); logger.info("aesdecodeParams: " + aesdecodeParams); //国密sm4,注意国密sm4的key是需要32位16进制字符 String sm4EncodeParams = Sm4Util.encryptEcb(params); logger.info("sm4EncodeParams: " + sm4EncodeParams); String sm4DecodeParams = Sm4Util.decryptEcb(sm4EncodeParams); logger.info("sm4DecodeParams: " + sm4DecodeParams); } }
    作者:CodingPanda
    座中铭:润物细无声,功到自然成
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    MySQL的max()函数使用时遇到的小问题
    scp命令需要指定端口时要紧跟在scp后
    linux系统之间基于密钥对免输入密码登陆
    c++的引用用法
    预测模型
    mysql出现ERROR 1366 (HY000):的解决办法
    R语言可视化--颜色
    R语言可视化--ggplot函数
    R语言可视化--qplot函数
    R语言可视化二
  • 原文地址:https://www.cnblogs.com/LiLiliang/p/15272269.html
Copyright © 2011-2022 走看看