完美解决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

智能推荐

以MapBox为核心构建Vue地图组件库教程_vue 省份 地图组件库-程序员宅基地

文章浏览阅读951次。不多废话直接讲干货,首先我们要清楚如何写一套组件库,类似于使用vue编写的elementui,使用react编写的antdesign等,我们现在要以GIS为核心写组件库,其实原理类似。一个是组件的主体vue文件,另一个是将组件局部暴露出去的index.js文件,当然你可以再此基础上增加你想要的其他的js文件和vue文件,上面讲的两个文件是必须的。这行命令可以将你写的组件库打包成压缩文件,一般是一个dist静态目录,在进行npm发布的时候也是将这个静态的dist发布在官网上。_vue 省份 地图组件库

【控制control】四足机器人弹簧加载倒立摆(SLIP)动力学模型_【控制control】四足机器人动力学模型-slip-程序员宅基地

文章浏览阅读4.9k次,点赞5次,收藏32次。系列文章目录提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加TODO:写完再整理文章目录系列文章目录前言1.动力学建模构型方法2.四足机器人动力学模型(1)多体动力学模型【针对躯干+脚建模】方法一:VMC( Virtual Model Controller)模型方法二:SLIP模型(2)浮基单体动力学模型【针对躯干建模】【用于MPC】前言认知有限,望大家多多包涵,有什么问题也希望能够与大家多交流,共同成长!本文先对四足机器人动力学模型-VMC、SLIP和浮动机体模型做个简_【控制control】四足机器人动力学模型-slip

html5手指点击速度,CPS手速测试 - 鼠标点击速度测试插件-程序员宅基地

文章浏览阅读1.2w次。CPS手速测试插件背景简介为了刺激客户的消费很多购物平台都推出来秒杀抢购的活动,在这个活动中如果你的手速慢就抢不到商品,所以有时我们会需要锻炼一下自己的手速,那如何知道自己的手速是快还是慢呢,在世界平均范围中又处于何种地步,今天小编为大家推荐一款可以检测自己手速的插件CPS手速测试。CPS手速测试插件简介CPS手速测试插件是一款可以在线测试鼠标点击速度的检测工具,它可以是1/3/5/10/15/3..._测速度插件

VLAN以及三层交换机_核心交换机如何查询vlan-程序员宅基地

文章浏览阅读2k次,点赞2次,收藏7次。VLAN以及三层交换机1、VLAN概述与优势1.1vlan概述1.2vlan优势1.3VLAN的分类Trunk概述三层交换技术1、VLAN概述与优势1.1vlan概述VLAN(Virtual Local Area Network),中文称为虚拟局城网。是一组逻辑上隔离的设备和用户。这些设备和用户不受物理位置限制,可根据部门成组等进行灵活划分,保障信息安全。同时隔绝广播信息,提升网络效能,防止广播风暴的产生。1.2vlan优势1. 限制广播域。广播域被限制在一个VLAN内,提高了网络处理能力。 2_核心交换机如何查询vlan

clearTimeout无效_cleartimeout不生效-程序员宅基地

文章浏览阅读7.3k次。如图所示clearTimeout接受id作为参数,所以检查一下是否传入的不是id因为默认情况下setTimeout方法是会返回id但有时候会返回一个setTimeout对象比如使用vsCode 开发的同学在使用setTimeout时会自动引入timer对象,此时setTimeout就会返回Timeout对象,此时只需要将对应的id传入即可或者直接将引用注掉..._cleartimeout不生效

安卓发送post请求_android post-程序员宅基地

文章浏览阅读1.6k次。在HTTP通信中使用最多的就是GET和POST了,GET请求可以获取静态页面,也可以把参数放在URL字符串的后面,传递给服务器。本文将使用标准Java接口HttpURLConnection,以一个实例演示如何使用POST方式向服务器提交数据,并将服务器的响应结果显示在Android客户端。在Android中,提供了标准Java接口HttpURLConnection和Apache接口HttpClient,为客户端HTTP编程提供了丰富的支持。将提交的数据写入Log\Log.php文件中。_android post

随便推点

HDU - 1272 小希的迷宫之独木桥(并查集的简单应用)-程序员宅基地

文章浏览阅读236次。小希的迷宫 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)_hdu - 1272

RAD Studio 11.2详解其务实改进(Delphi & C++ Builder)-Alexandria-程序员宅基地

文章浏览阅读7.4k次,点赞5次,收藏11次。● 开发人员生产力:“搬运式的复用”是一个特性。使用Delphi和C++Builder使得开发机构交付订单和市场需求的速度提高了5倍有余。● 快速的“原生”应用程序:操作系统本机的原生编译器,赋能App应用应有的原生速度(没有任何臃肿)。● 数据库访问:Delphi最原始的关键设计之一,就是将数据库访问完全集成到RAD Studio之中。● 强大的C++库:数百个C++库,可以在C++Builder中使用,或者在RAD Studio中的Delphi下使用。_rad studio

shiro@RequiresPermission校验实现_requirespermissions 校验的是-程序员宅基地

文章浏览阅读864次。shiro-spring借助Spring AOP特性实现shiro的注解式校验引入shiro-spring依赖后一定要注入AuthorizationAttributeSourceAdvisor以便借助spring aop进行shiro注解校验 @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) ..._requirespermissions 校验的是

唱响中国-红歌36首-刘和刚 - 好男儿就是要当兵-程序员宅基地

文章浏览阅读308次。歌曲下载/歌词下载:http://dl.iteye.com/topics/download/be412093-1ed9-3086-aeaf-e132ca9a1758刘和刚 - 好男儿就是要当兵歌词:好男儿就是要当兵刘和刚唱响中国-红歌36首当兵才知道帽徽为什么这样红当兵才知道肩章为什么这样重当兵才知道祖国的山河在心中咱当了兵才知道好男儿 嘿 就是要当兵当兵才知道过去的模样太放松当兵..._当兵的人才知道自己的骨头有多硬

探索iOS转场动画_ios 转场动画-程序员宅基地

文章浏览阅读1.5k次,点赞2次,收藏3次。iOS提供图像转场动画,可实现酷炫的转场特效。动画包括:溶解、折叠、复印机、闪烁、翻页、波纹、滑动等等。_ios 转场动画

Java 本地内存 & 直接内存 & 元空间_java 本地内存和直接内存-程序员宅基地

文章浏览阅读4.1k次,点赞7次,收藏26次。Java虚拟机在执行的时候会把管理的内存分配到不同的区域,这些区域称为虚拟机内存;同时对于虚拟机没有直接管理的物理内存,也会有一定的利用,这些被利用但不在虚拟机内存的地方称为本地内存。元空间不在虚拟机中,而是使用本地内存,JVM不会再出现方法区的内存溢出问题。..._java 本地内存和直接内存