问题
在tomcat8.5.X以上版本中,tomcat对请求入参做了严格校验,具体参考下文资料。
HTTP 400 Bad Request
...
http11.Http11Processor : Error parsing HTTP request header
java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
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:483)
org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:502)
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:818)
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1623)
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对特殊字符的限制(可以解除);
- get请求在浏览器地址栏的处理,不同浏览器的机制不一样(get请求可以通过指定tomcat配置URIEncoding="utf-8"来设置解码方式,默认为"ISO-8859-1",http和ajp都可配置);
- 除了get请求,其他请求方式可以通过spring filter配置来制定decode编码方式(当然对get请求也有效);
- 尽量不要传递含有特殊字符的变量,如果必须要传,那就通过encode/decode来实现;
- 尽量选择合适的请求方法和传递参数的方式,避免出错的可能性(如:post可避免传输大小限制和中文编码问题;传递key-value形式的参数比传递json格式更安全[减少大括号、引号、逗号带来的潜在编码问题]等)
/**
* 首选方案(终极方案):前端对请求参数进行编码,后端解码。
* <p/>
* 次选方案,配置tomcat connector参数如下(外置tomcat配置<Connector></Connector>属性):
*
* @see <a href="https://tomcat.apache.org/tomcat-8.5-doc/config/systemprops.html">[tomcat.util.http.parser.HttpParser.requestTargetAllow].This system property is deprecated.外置tomcat配置位置:$TOMCAT_HOME/conf/catalina.properties</a>
* @see <a href="https://tomcat.apache.org/tomcat-8.5-doc/config/http.html">relaxedPathChars & relaxedQueryChars</a>
* @see <a href="https://docs.spring.io/spring-boot/docs/2.1.8.BUILD-SNAPSHOT/reference/html/howto-embedded-web-servers.html">[spring-boot]howto-embedded-web-servers</a>
* @see <a href="https://bz.apache.org/bugzilla/show_bug.cgi?id=60594">RFC 7230/3986 url requirement that prevents unencoded curly braces should be optional, since it breaks existing sites</a>
* @see org/apache/tomcat/embed/tomcat-embed-core/8.5.32/tomcat-embed-core-8.5.32-sources.jar!/org/apache/tomcat/util/http/parser/HttpParser.java:125
*/
@Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
tomcat.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> {
connector.setAttribute("relaxedPathChars", " < > [ \\ ] ^ ` { | }");
connector.setAttribute("relaxedQueryChars", " < > [ \\ ] ^ ` { | }");
});
return tomcat;
}
关于乱码问题
参考(GET请求的中文乱码问题):
- https://www.zhihu.com/question/21861899
- https://blog.csdn.net/zcg1041bolg/article/details/76256338
- tomcat的server.xml中的UrIEncoding编码设置
- https://blog.csdn.net/hfs1992/article/details/77233707
- https://my.oschina.net/selfdesign/blog/514335
- https://blog.csdn.net/shiyong1949/article/details/79654995?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-4&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-4
- https://blog.csdn.net/sanai_1992/article/details/77336501