完美解决SpringCloud-gateway全局GlobalFilter获取post的请求参数截取导致获取参数不全_spring-cloud 2021.0.5 gatway post 参数问题-程序员宅基地

技术标签: SpringCloud  

我们在使用SpringCloud-gateway作为网关转发的时候,当post请求参数过程,刚好需要针对post请求体做相应的操作时候的,会发现每次获取的请求参数获取不全的问题,以下解决方法,来自于百度总结,实战可用;



@Component
public class DefaulFilter implements GlobalFilter, Ordered {

    public final static String REDIS_KEY_ACCESS_TOKEN_PLATFORM = "PLATFORM_ACCESS_TOKEN#";

    @Value(value = "${platform.publicKey}")
    private String publicKey;

    @Value(value = "${platform.privateKey}")
    private String privateKey;

    @Autowired
    @Qualifier(value = "excludeRequestMap")
    private Map<String, String> excludeRequestMap;

    private final List<HttpMessageReader<?>> messageReaders = HandlerStrategies.withDefaults().messageReaders();

    @Override
    public int getOrder() {
        return -2;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest serverHttpRequest= exchange.getRequest();
        // 符合条件请求直接放行:1.swagger文档请求接口  2.相关的登录请求接口
        if (excludeRequestMap.containsKey(serverHttpRequest.getURI().getPath())
                || HttpMethod.GET.equals(serverHttpRequest.getMethod())) {
            return chain.filter(exchange.mutate().request(exchange.getRequest()).build());
        }
        //判断是否为post请求
        if (HttpMethod.POST.equals(serverHttpRequest.getMethod())) {
            return processRequest(exchange, chain);
        }else if (HttpMethod.GET.equals(serverHttpRequest.getMethod())) {
            //1 判断是否为get请求
            return chain.filter(exchange);
        }
        return chain.filter(exchange);
    }

    private Mono<Void> processRequest(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerRequest serverRequest = new DefaultServerRequest(exchange, messageReaders);
        DataBufferFactory bufferFactory = exchange.getResponse().bufferFactory();
        Mono<String> rawBody = serverRequest.bodyToMono(String.class).map(s -> s);
        BodyInserter<Mono<String>, ReactiveHttpOutputMessage> bodyInserter = BodyInserters.fromPublisher(rawBody, String.class);
        //从head中获取敏感信息--机密后的json字符串
        HttpHeaders headers = exchange.getRequest().getHeaders();
        String platformEnExchangeInfo = headers.getFirst(LogFilterConstants.PLATFORM_EXCHANGE_INFO);
        SensitiveInfoView sensitiveInfoView=new SensitiveInfoView();
        //通过私钥解密获取解密后敏感信息-加密信息不为空
        if(StringUtils.isNotBlank(platformEnExchangeInfo)) {
            try {
                PrivateKey privateKeyEntity = RsaUtils.getPrivateKey(privateKey);
                String platformDeExchangeInfo = RsaUtils.decrypt(platformEnExchangeInfo, privateKeyEntity);
                //转换成json对象
                JSONObject jsonObject = JSONObject.parseObject(platformDeExchangeInfo);
                sensitiveInfoView = JSON.toJavaObject(jsonObject, SensitiveInfoView.class);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //把用户信息压入token中
        Map<String, Object> claimsMap = new HashMap<>();
//      claimsMap.put(LogFilterConstants.SENSITIVE_INFO_KEY, sensitiveInfoView);
        claimsMap.put("CLAIM_NAME_ID_NO",sensitiveInfoView.getIdNo());
        String newToken = JwtUtils.createAccessToken(sensitiveInfoView.getMobileNumber(),claimsMap, 1000);

        CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
        return bodyInserter.insert(outputMessage, new BodyInserterContext()).then(Mono.defer(() -> {
            Flux<DataBuffer> body = outputMessage.getBody();
            DataBufferHolder holder = new DataBufferHolder();
            body.subscribe(dataBuffer -> {
                int len = dataBuffer.readableByteCount();
                holder.length = len;
                byte[] bytes = new byte[len];
                dataBuffer.read(bytes);
                DataBufferUtils.release(dataBuffer);
                //修改请求体参数值
                String text = new String(bytes, StandardCharsets.UTF_8);
                JSONObject newBodyStr = JSONObject.parseObject(text);
                newBodyStr.put("token", newToken);
                text=newBodyStr.toJSONString();
                DataBuffer data = bufferFactory.allocateBuffer();
                data.write(text.getBytes(StandardCharsets.UTF_8));
                holder.dataBuffer = data;
            });
            ServerHttpRequestDecorator requestDecorator = new ServerHttpRequestDecorator(exchange.getRequest()) {

                @Override
                public HttpHeaders getHeaders() {
                    HttpHeaders httpHeaders = new HttpHeaders();
                    httpHeaders.putAll(super.getHeaders());
                    //由于修改了请求体的body,导致content-length长度不确定,因此使用分块编码
                    httpHeaders.remove(HttpHeaders.CONTENT_LENGTH);
                    httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
                    return httpHeaders;
                }
                @Override
                public Flux<DataBuffer> getBody() {
                    return Flux.just(holder.dataBuffer);
                }
            };
            return chain.filter(exchange.mutate().request(requestDecorator).build());
        }));
    }

    private class DataBufferHolder {
        DataBuffer dataBuffer;
        int length;
    }
}

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/pan4609/article/details/102777939

智能推荐

Black Scholes公式推导及求解 Part 1:BS Equation的推导_bs公式推导-程序员宅基地

文章浏览阅读4.7k次。Black-Scholes公式推导Black-Scholes公式推导Black-Scholes公式推导一、期权价格可以标识为关于标的资产价格S和时间t的函数V(S,t;σ,μ;E,T;r)V(S,t;\sigma,\mu;E,T;r)V(S,t;σ,μ;E,T;r)其中:SSS和ttt是标的资产价格和时间σ\sigmaσ和μ\muμ是标的资产的波动率和收益率EEE和TTT是期权合约的行权价格和到期时间rrr是无风险收益率二、BS公式的6个假设:标的资产价格服从一个已_bs公式推导

css 图片彩色变黑白的(滤镜效果)-程序员宅基地

文章浏览阅读4.3k次。html,body { -webkit-filter: grayscale(100%); -moz-filter: grayscale(100%); -ms-filter: grayscale(100%); -o-filter: grayscale(100%); filter: grayscale(100%); filter: gray; }

Kafka-初识_kafa pmq-程序员宅基地

文章浏览阅读483次。简介kafka是一个分布式的发布订阅消息系统(或者说是一个分布式流平台),可以实时处理大数据。我们可以把kafka比作水管,水管中可以承载水流,那么kafka可以承载数据流。kafka可以构建实时的流数据管道,来处理大量的数据流。消息系统kafka是一个优秀的消息系统,支持持久化,更关注吞吐量,显式的分布式。消息系统是什么? 消息系统负责将数据从一个应用程序传递到另一个应用程序..._kafa pmq

JQuery-程序员宅基地

文章浏览阅读2.9k次。目前除Prototype 之外最优秀的JavaScript Framework。Prototype已经把效果类库去掉,交给script.aculo.us和Rico这些二次开发的类库,专注于核心部份的开发。JQuery则把效果当作重要的部份。JQuery提供的文档比Prototype要齐全。如果你想同时使用Prototype和JQuery,看看:http://jquery.com/docs/Prot

modbus_tk库的使用和分析-程序员宅基地

文章浏览阅读2.6w次,点赞9次,收藏59次。目录modbus_tk库的使用和分析如何使用modbus_tk的主机和从机?主从Demo代码分析modbus_tk库函数主代码分析modbus_tk库的使用和分析modbus版本:0.5.7下载地址:https://github.com/ljean/modbus-tk1:应用示例程序2:web形式的主机端(bottle搭建的后台)3:modbus_tk..._modbus_tk

win10+vs2019+cuda11.0+cudnn8.0+tensorrt7.1.3.4配置与测试++tensorrt+yolo部署_tensorrt-7.1.3.4/lib/libnvinfer.so: undefined refe-程序员宅基地

文章浏览阅读2.6k次,点赞4次,收藏17次。一 cuda11.0安装1 打开官网(https://developer.nvidia.com/cuda-toolkit-archive),选择11.02 运行安装包,选择自定义安装(第一安装可以全选)3 路径选择的是默认位置,后面一路默认就OK,安装成功关闭。4 安装结束后,右键 我的电脑–>属性–>高级系统设置–>环境变量,系统变量中已经加入了cuda的两个路径。5 在系统变量中加入下面的路径,点击确定.CUDA_BIN_PATH: %CUDA_PATH%\bin_tensorrt-7.1.3.4/lib/libnvinfer.so: undefined reference to `cudnnpoolingforw

随便推点

浅谈估值模型:PB指标与剩余收益估值_pbroe估值模型-程序员宅基地

文章浏览阅读2.4k次,点赞5次,收藏9次。本文简单介绍PB指标,剩余收益的推导及其估值方式_pbroe估值模型

c++ 获取特定目录下的文件夹个数_c++ 文件夹文件个数-程序员宅基地

文章浏览阅读9.6k次,点赞2次,收藏10次。项目需求,需要计算某一项操作前后文件夹的个数增加了多少,实现了一下。主要用到了#include&lt;io.h&gt;库,十分给力。//计算文件夹的个数int OERSProductLayer::visit(string path, int layer){ struct _finddata_t filefind; string curr = path + "\\*.*"; int ..._c++ 文件夹文件个数

简易版“美颜”来了!肝了一夜!用Python做一个高瘦脸神器!-程序员宅基地

文章浏览阅读2.2k次,点赞2次,收藏14次。“菜鸟学Python”,第“519”篇原创如今的网络时代,许多直播的博主们,在进行 直播时,都喜欢利用美颜的方式来提升自己的颜值。其中必不可少的就是瘦脸。瘦脸更能够显示出自己美丽的五官轮廓..._用python实现瘦脸

视觉SLAM笔记(31) 特征提取和匹配_opencv4 特征匹配 对号和错号-程序员宅基地

文章浏览阅读1.2w次,点赞2次,收藏4次。根据两张具有微小运动的图片,提取 ORB 特征并匹配_opencv4 特征匹配 对号和错号

【图解】cpu,内存,硬盘,指令的关系-程序员宅基地

文章浏览阅读294次。1 程序员用高级语言编写程序。2 经过编译 链接等形成机器语言的EXE文件。3 EXE文件保持在磁盘的某个或多个扇区内4 程序运行是在内存中生成EXE的副本5 将指令读入cpu的寄存器6 由cpu中的控制器,运算器,和时钟配合解析运行1 程序员用高级语言编写程序。程序员并不直接和内存和cpu打交道,程序员只是负责编写代码,现在程序猿更是使用高级语言来..._指令在cpu的关系图

也谈Sybase ASE15.x在Windows下的静态安装(silent install)-程序员宅基地

文章浏览阅读185次。Sybase ASE数据库的图形界面安装,虽然比较顺利,但是也让中文用户很不爽,那就是字符集的选择,似乎没有余地,只能Customize选择,还不一定一次能选对。比如,你一路安装的时候, ASE sql server创建的时候,很难从界面里头选择语言和字符集。还好,ASE15.x提供了silent install的方式。1. 安装并生成silent install的配置文件运行setupc..._ase 默认语言 us_english

推荐文章

热门文章

相关标签