url中包含类似"|[]/|{}"等特殊字符导致请求报400错误的解决办法

1. 问题


今天测试使用get请求参数合同编号包含一些特殊字符([]或者{}),报400错误,并提示如下错误信息:

HTTP Status 400 – Bad Request Type Exception Report Message Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986 Description The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing). Exception java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986 org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:468) org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:260) org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860) org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1598) org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) java.base/java.lang.Thread.run(Thread.java:830) Note The full stack trace of the root cause is available in the server logs.

2. 解决方案


问题非常明显,提示已经足够清楚了。

经过复现测试提供的问题,发现部分老的js代码没有遵循规范,在url的请求参数中携带了原始的没有经过url encode 转码的json字符串。json字符串中的{}显然不属于 RFC 7230 和 RFC 3986 允许的特殊字符。

2.1. 彻底的解决方案

彻底的解决方案显然应该是重构代码,让代码遵循规范。

所有的url参数都应该经过url encode,确保不会出现特殊字符

复杂请求参数应当通过 post,放在Request Body中传递,而不是 get 的url中显式传递。

2.2. 临时解决方案

问题已经出现。而且经过初步检查,发现存在类似问题的不规范老代码太多,一时半会不能保证能全部修改完毕。那么彻底的解决方案就不可行的。对应急处理,还是有办法的:

2.2.1. 对tomcat6、tomcat7、tomcat8:

在 ${tomcat.dir}/conf/catalina.properties 文件中,找到被注释调的参数tomcat.util.http.parser.HttpParser.requestTargetAllow,取消备注,将该参数的值指定为:tomcat.util.http.parser.HttpParser.requestTargetAllow=|{}。这样,“|{}”这三个特殊字符就不再被拦截了。

2.2.2. 对tomcat9:

tomcat9不支持参数tomcat.util.http.parser.HttpParser.requestTargetAllow,但有类似的配置项。

在 ${tomcat.dir}/conf/server.xml 文件中,找到你使用的Connector,添加参数relaxedPathChars="|{}" relaxedQueryChars="|{}"。

2.2.3. 对spring-boot的内嵌tomcat9以前版本:

如果是内嵌的 tomcat9以前版本,可以通过如下代码配置:

@SpringBootApplication public class XxApplication { public static void main(String[] args) { System.setProperty("tomcat.util.http.parser.HttpParser.requestTargetAllow","|{}"); SpringApplication.run(XxApplication.class, args); } ... } 

2.2.4. 对spring-boot内嵌的tomcat9:

可以通过类似如下代码添加Connector的自定义参数:

spring-boot-1.*可以这样:

@Component public class MyEmbeddedServletContainerCustomizer implements EmbeddedServletContainerCustomizer { @Override public void customize(ConfigurableEmbeddedServletContainer container) {

TomcatEmbeddedServletContainerFactory factory = (TomcatEmbeddedServletContainerFactory) container; factory.addConnectorCustomizers((connector) -> {

connector.setAttribute("relaxedPathChars", "|{}");

connector.setAttribute("relaxedQueryChars", "|{}"); }); } }

spring-boot-2.*可以这样

@Component public class MyTomcatServletWebServerFactoryCustomizer extends TomcatServletWebServerFactoryCustomizer {      public MyTomcatServletWebServerFactoryCustomizer(ServerProperties serverProperties) {

super(serverProperties); }

@Override public void customize(TomcatServletWebServerFactory factory) {

super.customize(factory);

factory.addConnectorCustomizers((connector) -> {

connector.setAttribute("relaxedPathChars", "|{}");

connector.setAttribute("relaxedQueryChars", "|{}");

});

}

}

你可能感兴趣的:(url中包含类似"|[]/|{}"等特殊字符导致请求报400错误的解决办法)