R F C 7230 R F C 3986

RFC 7230 and RFC 3986 错误

问题

在使用 内嵌 Tomcat 的时候,有些请求会报以下错误:

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.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	java.lang.Thread.run(Thread.java:748)
Note The full stack trace of the root cause is available in the server logs.

原因

Tomcat 8.0 以后对请求 URL 做了严格的过滤,Url 中只允许包含英文字母 a-zA-Z、数字 0-9-_.~ 4个特殊字符以及所有保留字符(! * ' ( ) ; : @ & = + $ , / ? # [ ]

RFC3986之URL编码与解码、AFPercentEscapedStringFromString

解决方案

  • 对特殊字符进行 url 编码
  • 使用 post 请求
  • 修改参数,方法如下
@Bean
public ConfigurableServletWebServerFactory webServerFactory() {
    TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
    factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
        @Override
        public void customize(Connector connector) {
            connector.setProperty("relaxedQueryChars", "|{}[]");
        }
    });
    return factory;
}

Read More