问题描述
Tomcat 8.5.7+,当Get请求中包含了未经编码的中文字符时,会报以下错误,请求未到应用程序在Tomcat层就被拦截了,并返回http 400错误。
Tomcat报错:
java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
问题原因
Tomcat在Tomcat 7.0.73+,Tomcat 8.0.39+,Tomcat 8.5.7+,Tomcat 9.0.0.M12 (markt)+版本后,在http url解析时做了严格字符限制,url包含特殊字符将直接返回http code 400
RFC 3986
Tomcat7.0.73添加了RFC 3986
这个规范。RFC 3986文档对Url的编解码问题做出了详细的建议,指出了哪些字符需要被编码才不会引起Url语义的转变,以及对为什么这些字符需要编码做出了相应的解释。
RFC 3986文档规定,Url中只允许包含英文字母(a-zA-Z
)、数字(0-9
)、-_.~
4个特殊字符以及所有保留字符! * ' ( ) ; : @ & = + $ , / ? # [ ]
。当在URL中使用保留字符时,需要对保留字符进行转义。(还有一些字符当直接放在Url中的时候,可能会引起解析程序的歧义,这些字符被视为不安全字符。)
空格
:Url在传输的过程,或者用户在排版的过程,或者文本处理程序在处理Url的过程,都有可能引入无关紧要的空格,或者将那些有意义的空格给去掉。引号以及<>
:引号和尖括号通常用于在普通文本中起到分隔Url的作用#
:通常用于表示书签或者锚点%
:百分号本身用作对不安全字符进行编码时使用的特殊字符,因此本身需要编码{}|\^[]
~`:某一些网关或者传输代理会篡改这些字符
requestTargetAllow
$TOMCAT_HOME/conf/catalina.properties
,添加属性 tomcat.util.http.parser.HttpParser.requestTargetAllow=|{}
该参数只支持|
、{
、}
三个参数的拦截过滤
该系统参数在高版本
tomcat.util.http.parser.HttpParser.requestTargetAllow
已废弃,Tomcat让使用Connector
中的relaxedPathChars
及relaxedQueryChars
代替
relaxedQueryChars
$TOMCAT_HOME/conf/server.xml
,Connector
添加relaxedQueryChars
属性
Tomcat多实例则修改
$TOMCAT_BASE/catalina_base/conf/server.xml
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
relaxedQueryChars="[]|{}^\`"<>"
redirectPort="8443" />
参考资料: