Spring Boot 遇到 RFC 7230 and RFC 3986 的问题

发布于:12/14/2021, 4:04:39 PM @孙博
技术分享 | Spring Boot,Tomcat,RFC 7230,RFC 3986
许可协议:署名-非商业性使用(by-nc)

分享一个小案例。

这两天因为 log4j 的天坑导致别的事情都没做,光升级组件了。恰巧手上有个老项目顺便需要升级一下 spring-boot,从 https://mvnrepository.com/ 上查到今天最新的版本是 2.1.6 于是便直接升级了,然后问题发生了。

线上的服务忽然开始报 400 Bad Request 错误,查了下错误日志,看到了这个提示:Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986。虽然26个字母我都认识,但他们连成的这句话让我还是不知道如何解决。百度一下发现是因为请求的字符串中包含了 |,尽管最佳的解决方式是在请求端做一次 encode,但这种 native 的线上项目是不可能在短时间内完成全量升级的。

既然知道了根本原因就开始尝试修改。


方法1

在 tomcat 配置中增加 tomcat.util.http.parser.HttpParser.requestTargetAllow=|

因为是内嵌的 tomcat 所以方法不可用。

方法2

在项目启动时使用 System.setProperty("tomcat.util.http.parser.HttpParser.requestTargetAllow", "1")

估计还是因为内嵌 tomcat 的原因结果还是无法生效

方法3

修改 relaxedQueryChars
代码如下

    @Bean
    public ConfigurableServletWebServerFactory webServerFactory() {
        TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
        factory.addConnectorCustomizers(
                (TomcatConnectorCustomizer) connector -> connector.setProperty("relaxedQueryChars", "|{}[]\\"));
        return factory;
    }

启动运行,使用带有 | 的查询参数,正常运行没有报错


问题解决。