4

Tomcat中URI不支持特殊字符解决方案

 3 years ago
source link: https://eelve.com/archives/tomcatillegalargumentexception
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

前情提要】最近开发过程中遇到一个TomcatIllegalArgumentException的报错,所以在这里记录一下。

壹、错误现象

在用Get请求是当URL中包含特殊字符,比如:<>(){}|等时,Tomcat会报出以下错误:

java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
    at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:476) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:687) ~[tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_161]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_161]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.28.jar:8.5.28]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_161]

贰、故障原因

因为Tomcat严格按照 RFC 3986规范进行访问解析,而 RFC 3986规范定义了Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符(RFC3986中指定了以下字符为保留字符:! * ’ ( ) ; : @ & = + $ , / ? # [ ])。传入的参数中有"{"不在RFC3986中的保留字段中,所以会报参数异常错。而且这个错误你在应用中处理不到,因为根本都还没有进入应用,在Tomcat中就已经报错了,而且就连你在Tomcat中配置错误页面也没有用。

叁、解决方案

3.1、定义requestTargetAllow属性

Tomcat 7.0.76, 8.0.42, 8.5.12 这些版本之后可以定义requestTargetAllow 属性来允许禁止的字符。在tomcat的 catalina.properties文件中添加这一句:

tomcat.util.http.parser.HttpParser.requestTargetAllow=|{}

3.2、修复server.xml配置文件

如果某些版本的Tomcat已经参照3.1中的方法修改之后,还是不生效的话。从官网的文档中我们可以查看到如下提示:tomcat.util.http.parser.HttpParser. requestTargetAllow(This system property is deprecated. Use the relaxedPathChars and relaxedQueryChars attributes of the Connector instead)

所有我们在Tomcat配置文件中:$CATALINA_HOME/conf/server.xml添加relaxedQueryChars属性添加到Connector元素:

<connector port="8080" protocol="HTTP/1.1" connectiontimeout="20000" uriencoding="UTF-8" relaxedquerychars="[]|{}^\`"<>" redirectport="8443">

3.3、Springboot修改方法

在SpringBootApplication的的main方法中增加

System.setProperty("tomcat.util.http.parser.HttpParser.requestTargetAllow","|{}");

另外在Springboot 2.0 之后的版本,可以自定义WebServerFactoryCustomizer,添加特殊字符的支持:

import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;import org.springframework.boot.web.server.WebServerFactoryCustomizer;import org.springframework.stereotype.Component; /** * Created on 2019/2/18 17:41. * * @author Ethan * <p> * java.lang.IllegalArgumentException: *  Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986. * </p> */@Componentpublic class PortalTomcatWebServerCustomizer implements WebServerFactoryCustomizer<tomcatservletwebserverfactory> {     @Override    public void customize(TomcatServletWebServerFactory factory) {        factory.addConnectorCustomizers(connector -> connector.setAttribute("relaxedQueryChars", "{}[]|"));    }}

薏米笔记

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK