Tomcat 8无法处理查询参数中带有“ |”的获取请求?

我正在使用 Tomcat 8。在一种情况下,我需要处理来自外部源的外部请求,其中请求有一个参数,它由 |分隔。

请求是这样的:

http://localhost:8080/app/handleResponse?msg=name|id|

在这种情况下,我得到下面的错误。

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:467)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:667)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:789)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)

编辑1

它适用于 ApacheTomcat 8.0.30,但不适用于 Tomcat 8.5

160795 次浏览

逃离它。管道符号是一个随着时间和浏览器之间的不同而处理的符号。例如,Chrome 和 Firefox 在复制/粘贴 URL 时使用管道转换 URL 的方式不同。然而,对于 Tomcat 8.5来说,最兼容、也是最必要的就是避免使用它:

Http://localhost:8080/app/handleresponse?msg=name%7cid%7c

在所有主要的 Tomcat 发行版中都引入了这种行为:

  • 雄猫 7.0.738.0.398.5.7

要修复,请执行下列操作之一:

  • 设置 relaxedQueryChars以允许这个字符 (建议,看看林肯的回答)
  • 设置 requestTargetAllow选项 (在 Tomcat 8.5中弃用)(看杰瑞米的回答)。
  • 您可以降级到较旧的版本之一(不推荐-安全性)

基于 更改日志,这些变化可能会影响这种行为:

雄猫8.5.3:

确保使用400响应拒绝具有非标记的 HTTP 方法名称的请求(如 RFC7231所要求的)

雄猫8.5.7:

为 HTTP 请求行解析添加额外的有效字符检查,以便更快地拒绝无效请求行。


最佳选择(遵循标准) -您想在客户端上对 URL 进行编码:

encodeURI("http://localhost:8080/app/handleResponse?msg=name|id|")
> http://localhost:8080/app/handleResponse?msg=name%7Cid%7C

或者只是查询字符串:

encodeURIComponent("msg=name|id|")
> msg%3Dname%7Cid%7C

它将保护您免受其他有问题的字符(无效 URI 字符列表)的攻击。

由于 Tomcat7.0768.0.428.5.12可以定义属性 requestTargetAllow来允许禁用字符。

catalina.properties中添加这一行

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

URI 被编码为 UTF-8,但 Tomcat 将其解码为 ISO-8859-1。您需要编辑 server.xml 中的连接器设置并添加 URIEncoding = “ UTF-8”属性。

或者在 application.properties 上编辑此参数

Uri-coding = utf-8

自 Tomcat 8.5: 公猫的官方文件以来,参数 tomcat.util.http.parser.HttpParser.requestTargetAllow已被弃用。

可以在连接器定义中使用 relaxedQueryChars / relaxedPathChars来允许这些字符: 公猫的官方文件

问题: Tomcat (7.0.88)抛出以下异常,导致400-Bad Request。

java.lang.IllegalArgumentException: Invalid character found in the request target.
The valid characters are defined in RFC 7230 and RFC 3986.

从7.0.88开始,大多数 tomcat 版本都出现了这个问题。

解决方案: (Apache 团队建议) :

Tomcat 增强了它们的安全性,不再允许查询字符串中使用原始的方括号。在请求中,我们有[ ,](方括号) ,因此服务器不处理请求。

在 server.xml (% TOMCAT _ HOME%/conf)下的标记下添加 relaxedQueryChars属性:

<Connector port="80"
protocol="HTTP/1.1"
maxThreads="150"
connectionTimeout="20000"
redirectPort="443"
compression="on"
compressionMinSize="2048"
noCompressionUserAgents="gozilla, traviata"
compressableMimeType="text/html,text/xml"
relaxedQueryChars="[,]"
/>

如果应用程序需要更多 Tomcat 默认不支持的特殊字符,那么在 relaxedQueryChars属性中添加这些特殊字符,如上所示,以逗号分隔。

在 server.xml 中添加“ relxedQueryChars”属性对我来说很有用:

<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="443" URIEncoding="UTF-8" relaxedQueryChars="[]|{}^&#x5c;&#x60;&quot;&lt;&gt;"/>