-->

Tomcat 8 is not able to handle get request with &#

2019-01-11 00:34发布

问题:

I am using Tomcat 8. In one case I need to handle external request coming from external source where the request has a parameters where it is separated by |.

Request is looks like this:

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

In this case I am getting following error.

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)

EDIT 1

It works with Apache Tomcat 8.0.30 but not with Tomcat 8.5

回答1:

This behavior is introduced in all major Tomcat releases:

  • Tomcat 7.0.73, 8.0.39, 8.5.7

To fix, do one of the following:

  • set relaxedQueryChars to allow this character (recommended, see Lincoln's answer)
  • set requestTargetAllow option (deprecated in Tomcat 8.5) (see Jérémie's answer).
  • you can downgrade to one of older versions (not recommended - security)

Based on changelog, those changes could affect this behavior:

Tomcat 8.5.3:

Ensure that requests with HTTP method names that are not tokens (as required by RFC 7231) are rejected with a 400 response

Tomcat 8.5.7:

Add additional checks for valid characters to the HTTP request line parsing so invalid request lines are rejected sooner.


The best option (following the standard) - you want to encode your URL on client:

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

or just query string:

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

It will secure you from other problematic characters (list of invalid URI characters).



回答2:

Since Tomcat 7.0.76, 8.0.42, 8.5.12 you can define property requestTargetAllow to allow forbiden characters.

Add this line in your catalina.properties

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


回答3:

The parameter tomcat.util.http.parser.HttpParser.requestTargetAllow is deprecated since Tomcat 8.5: tomcat official doc.

You can use relaxedQueryChars / relaxedPathChars in the connectors definition to allow these chars: tomcat official doc.



回答4:

The URI is encoded as UTF-8, but Tomcat is decoding them as ISO-8859-1. You need to edit the connector settings in the server.xml and add the URIEncoding="UTF-8" attribute.

or edit this parameter on your application.properties

server.tomcat.uri-encoding=utf-8



回答5:

We found the same issue . After analyzing the issue , found the solution . Below are the details for issue and solution.

Issue: Tomcat (7.0.88) is throwing below exception which leads to 400 – Bad Request. java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986. This issue is occurring most of the tomcat versions from 7.0.88 onwards.

Solution: (Suggested by Apache team):

Tomcat increased their security and no longer allows raw square brackets in the query string. In the request we have [,] (Square brackets) so hotel request is not processing by server.
As a solution below are the steps needs to be incorporate to make it work as expected. 1. We need to add relaxedQueryChars attribute under tag under server.xml (%TOMCAT_HOME%/conf)

          <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="[,]"
             />
  1. If application needs more special characters which is not supported by tomcat by default then we need add those special characters in relaxedQueryChars attribute with comma separated as above.


回答6:

Escape it. The pipe symbol is one that has been handled differently over time and between browsers. For instance, Chrome and Firefox convert a URL with pipe differently when copy/paste them. However, the most compatible, and necessary with Tomcat 8.5 it seems, is to escape it:

http://localhost:8080/app/handleResponse?msg=name%7Cid%7C