SpringCloud + SpringGateway 解决Get请求传参为特殊字符导致400无法通过网关转发的问题

这篇具有很好参考价值的文章主要介绍了SpringCloud + SpringGateway 解决Get请求传参为特殊字符导致400无法通过网关转发的问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


title: “SpringCloud + SpringGateway 解决Get请求传参为特殊字符导致400无法通过网关转发的问题”
createTime: 2021-11-24T10:27:57+08:00
updateTime: 2021-11-24T10:27:57+08:00
draft: false
author: “Atomicyo”
tags: [“tomcat”]
categories: [“java”]
description: “SpringCloud + SpringGateway 解决Get请求传参为特殊字符导致400无法通过网关转发的问题”


SpringCloud + SpringGateway 解决Get请求传参为特殊字符导致400无法通过网关转发的问题

场景:

公司以前的框架统一使用Post请求,传入参数为一个定义的公共类,类里面有个String类型的bean字段传入json字符串作为传参,emmm就想给他改成restful风格,在传入参数公共类无法改变的情况下,Get请求会传入特殊字符,导致400错误。例如:

localhost:10001/verify/compreport/month?data={"compRefOwid":"1448487922485252098", "yhMonth":"2021-10"}

原因:

Tomcat的新版本中增加了一个新特性,就是严格按照 RFC 3986规范进行访问解析,而 RFC 3986规范定义了Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符(RFC3986中指定了以下字符为保留字符:! * ’ ( ) ; : @ & = + $ , / ? # [ ])。

解决方案选择:

  1. 前端请求时encode特殊字段(算了,不能因为自己的原因加大前端工作量)
  2. 改用post请求(emmm没有办法的办法,看着难受就是想要改了)
  3. 改Tomcat配置文件(由于是springboot项目,内嵌了tomcat,不方便修改,好吧就是我比较菜)
  4. 在后端代码层面解决这个问题

解决方法:

其他服务:由于使用的是内嵌的tomcat,网上常见的
解决spring boot请求包含非法字符问题 The valid characters are defined in RFC 7230 and RFC 3986 错误
配置TomcatServletWebServerFactory的方式使用时会导致两个TomcatServletWebServerFactory使springboot项目报错Unable to start ServletWebServerApplicationContext due to multiple ServletWebServerFactory beans而无法启动。而使用yml配置的方式也无法生效。

server:
  tomcat:
    relaxed-query-chars:
      - "<"
      - ">"
      - "["
      - "]"
      - "{"
      - "}"

随后参考了继承WebServerFactoryCustomizer的方式来修改Tomcat配置

SpringBoot2.0.0新版本内嵌Tomcat配置

import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;

/**
 * Tomcat配置
 * @author Atomicyo
 * @version 1.0
createTime: 2021-11-24T10:27:57+08:00
updateTime: 2021-11-24T10:27:57+08:00
 */
@Component
public class MyTomcatWebServerCustomize implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {

    private int maxParameterCount = 10000;

    @Override
    public void customize(TomcatServletWebServerFactory factory) {
        PropertyMapper propertyMapper = PropertyMapper.get();
        propertyMapper.from(this::getMaxParameterCount)
                .when(v -> true)
                .to(v -> customizerProperty(factory));
    }

    /**
     * params特殊字符过滤
     * @param factory
     * @return void
     * @author Atomicyo
createTime: 2021-11-24T10:27:57+08:00
updateTime: 2021-11-24T10:27:57+08:00
     * @version 1.0
     */
    private void customizerProperty(TomcatServletWebServerFactory factory) {
        factory.addConnectorCustomizers(
                connector -> connector.setProperty("relaxedQueryChars", "[]{}"));
    }

    public void setMaxParameterCount(int maxParameterCount) {
        this.maxParameterCount = maxParameterCount;
    }

    public int getMaxParameterCount() {
        return maxParameterCount;
    }
}

网关模块:

由于spring gateway使用的是netty作为服务。所以修改tomcat配置的方式无法生效。参考Spring Cloud Gateway 和 Webflux 请求参数非法字符处理

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.HttpRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;
import reactor.netty.ConnectionObserver;
import reactor.netty.NettyPipeline;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

/**
 * Netty编码配置
 * @author Atomicyo
 * @version 1.0
createTime: 2021-11-24T10:27:57+08:00
updateTime: 2021-11-24T10:27:57+08:00
 */
@Component
@Slf4j
public class EncodeQueryNettyWebServerCustomizer implements WebServerFactoryCustomizer<NettyReactiveWebServerFactory> {

    /**
     * 需要encode的特殊字符
     */
    private final List<Character> charList = new ArrayList<Character>() {
        {
            this.add('{');
            this.add('}');
            this.add('[');
            this.add(']');
        }
    };

    @Override
    public void customize(NettyReactiveWebServerFactory factory) {
        factory.addServerCustomizers(httpServer ->
                httpServer.observe((conn, state) -> {
                    if (state == ConnectionObserver.State.CONNECTED) {
                        conn.channel().pipeline().addAfter(NettyPipeline.HttpCodec, "",  new QueryHandler());
                    }
                }));
    }


    class QueryHandler extends ChannelInboundHandlerAdapter {

        public QueryHandler() {
        }

        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws UnsupportedEncodingException {
            if (msg instanceof HttpRequest) {
                HttpRequest request = (HttpRequest) msg;
                String url = request.uri();
                // fix url
                log.info("url: {}", url);
                String[] split = url.split("\\?");
                StringBuilder fixUrl = new StringBuilder(split[0]);
                if (split.length > 1) {
                    fixUrl.append("?");
                    char[] chars = split[1].toCharArray();
                    for (char aChar : chars) {
                        if (charList.contains(aChar)) {
                            fixUrl.append(URLEncoder.encode(String.valueOf(aChar), "UTF-8"));
                        }else {
                            fixUrl.append(aChar);
                        }
                    }
                }
                log.info("fixUrl: {}", fixUrl);
                request.setUri(fixUrl.toString());
            }
            ctx.fireChannelRead(msg);
        }
    }
}

验证:

SpringCloud + SpringGateway 解决Get请求传参为特殊字符导致400无法通过网关转发的问题,spring cloud,spring,后端,android文章来源地址https://www.toymoban.com/news/detail-727794.html

到了这里,关于SpringCloud + SpringGateway 解决Get请求传参为特殊字符导致400无法通过网关转发的问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • axios中get、post请求传参区别及使用

    params 中的参数是通过地址栏传参,一般用于get请求 data 是添加到请求体(body)中的, 一般用于post请求 get请求只能传query参数,query参数都是拼在请求地址上的 post可以传body和query两种形式的参数 一般情况下post请求方式的Parameter Type是body,在一些极少情况下,post请求的参数

    2024年02月14日
    浏览(48)
  • uniapp发起post和get请求——this.$http.get 和 this.$http.post传参

    main.js按照内容自行修改

    2024年02月15日
    浏览(53)
  • 学习笔记230810--vue项目中get请求的两种传参方式

    问题描述 今天写了一个对象方式传参的get请求接口方法,发现没有载荷,ip地址也没有带查询字符串,数据也没有响应。 代码展示 错误分析 实际上这里的 query 是对象方式带参跳转的参数名,而get方法对象方式传参的参数名是parmas 解决方法 get请求有两种带参的方式 方式1 :

    2024年02月10日
    浏览(44)
  • 前端传参中带有特殊符号导致后端接收时乱码或转码失败的解决方案

    项目中采用富文本编辑器后传参引起的bug,起因如下: 数据库中存入的数据会变成这种未经转码的URL编码 使用JSON方式传参,但富文本编辑器不支持将内容转成JSON,会遗失标签,显然不符合把富文本文章存入数据库的需求,所以PASS 使用URL拼接方式传参,而缺点也是明显的,

    2024年01月25日
    浏览(50)
  • SpringGateway网关(Spring Gateway是Spring自己编写的,也是SpringCloud中的组件)

    目录 SpringGateway网关 奈非框架简介 什么是网关 网关的主要功能有 Spring Gateway简介 网关路由配置 动态路由 早期(2020年前)奈非提供的微服务组件和框架受到了很多开发者的欢迎 这些框架和SpringCloud Alibaba的对应关系我们要了解 现在还有很多旧项目维护是使用奈非框架完成的微

    2024年02月09日
    浏览(48)
  • 前端提交post请求却变成get请求的原因及解决方法

    导语:笔者在vue2项目中,使用axios封装post请求,提交请求时却变成get请求 编写登录方法时,把method敲成methods,而且又看到了提示就直接使用了(太粗心😭) [ Axios 中文文档 ] 改成如下代码即可 · 浏览器的默认请求模式是GET     当我们在浏览器地址栏中输入一个网址或单击链

    2024年02月06日
    浏览(94)
  • 【查错解决过程】Postman测试接口GET请求404(使用IDEA解决)

    现在在使用postman进行代码测试的时候一直报404, 不知道问题到底出在哪里。 基本的GET请求都不能成功...   然后我就发现可能是我没有加上@MapperScan的声明。 后来发现不是,至今也不知道eclipse怎么调。 ————————————————————————————————

    2024年02月03日
    浏览(44)
  • 不支持请求方法POST或GET的一种解决方法

    Request method ‘POST‘ not supported(已解决) 该错误一般是请求类型对不上导致的,比如PostMapping和GetMapping请求,一般错误发生在下图所示位置,我把Post和Get搞错了。 值得说的一点是,因为我不确定是不是这里错了,所以一开始我并没有把GetMapping注释掉,我认为在下面加上PostMa

    2024年02月12日
    浏览(49)
  • URL传参时,参数包含有特殊字符(%、#、&)的处理方法

    uniapp项目中页面跳转时,通过url传参,参数为一个包含特殊的字符的对象并内容比较多,导致不能正常传参 1、有些符号在URL中是不能直接传递的,如果要在URL中传递这些特殊符号,那么就要使用他们的编码了。编码的格式为:%+字符的ASCII码,即一个百分号%,后面跟对应字符

    2024年02月11日
    浏览(35)
  • 原生js XMLHttpRequest发送 get post 请求 解决跨域 及 注意事项

    2、使用xhr发起GET请求 四个步骤: ①:创建 xhr对象 ②:调用 xhr的open()函数(open中传递两个参数,参数一是GET/POST请求方式,参数二是请求的URL地址) ③:调用 xhr.send()函数 ④:监听 xhr.onreadystatechange事件 xhr发起GET请求的完整代码 直接上示例 报错内容是这个 Failed to execute

    2024年02月16日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包