终极解决方案:

Invalid character found in the request target. The valid characters are defined in RFC 3986

25-Aug-2018 11:27:27.086 信息 [http-nio-8087-exec-5] org.apache.coyote.http11.Http11Processor.service Error parsing HTTP request header
Note: further occurrences of HTTP header parsing errors will be logged at DEBUG level.
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:479)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:684)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:800)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1471)
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:748)

从错误日志中看到Error parsing HTTP request header

负责解析http请求的是org.apache.tomcat.util.http.parser.HttpParser,它对请求对URL中对字符做了限制,具体代码如下:

IS_NOT_REQUEST_TARGET[]中定义了一堆not request target

if(IS_CONTROL[i] || i > 127 || i == 32 || i == 34 || i == 35 || i == 60 || i == 62 || i == 92 || i == 94 || i == 96 || i == 123 || i == 124 || i == 125) {
IS_NOT_REQUEST_TARGET[i] = true;
}

转换过来就是以下字符(对应10进制ASCII),也就是URL中不能包含的特殊字符:

键盘上那些控制键:(<32或者=127)
非英文字符(>127)
空格(32)
双引号(34)
#(35)
<(60)
>(62)
反斜杠(92)
^(94)
TAB上面那个键,~(96)
{(123)
}(124)
|(125)

我碰到这个问题也捣弄了半天,参照其他的各种解决方案都不行。并且我是使用了多种特殊字符,运用单一某种方案还不能完全奏效。下面是经过实践的解决方案,请按顺序读完。

解决办法(亲测)

在conf/catalina.properties中最后添加2行:

tomcat.util.http.parser.HttpParser.requestTargetAllow=|{}
org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true

该方式,在所有Tomcat版本均适用。

解析:在执行请求时,碰到该没问题的,大多是在URL中传输Json等。尤其是用浏览器地址输入的URL死活不能包含有任何特殊字符。否则会返回400 状态码。

首先:不推荐降低tomcat版本,这等于掩耳盗铃,绝对得不偿失。

Tomcat在 7.0.73, 8.0.39, 8.5.7 版本后,在http解析时做了严格限制。

RFC3986文档规定,请求的Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符。

如果要使用这些特殊字符,并不是绝对不可以。Tomcat做了限制的同时,也提供了相关配置。给出的解决方案第一行requestTargetAllow,指定了允许的特殊字符,在等号后面配|{}就行了。

如果你仅需要使用这三个字符,配置到此就OK了。重启tomcat,rebuild工程再启动,就能正常使用了。

不幸的是, requestTargetAllow 只能配置|、{、} 允许这三个字符,对于其他的(例如" < > [ \ ] ^ ` { | } .),在请求时,仍然拦截,如果使用了|{}之外的其他字符那怎么办呢?那就还需要如下配置。

在conf/server.xml中的节点中,添加2个属性:

relaxedPathChars="|{}[],"
relaxedQueryChars="|{}[],"

这2个属性,可以接收任意特殊字符的组合,根据需要可以自行增减。

与此相关的文档说明:

讲解:tomcat.util.http.parser.HttpParser. requestTargetAllow

文档地址:https://tomcat.apache.org/tomcat-8.5-doc/config/systemprops.html

讲解:relaxedPathChars,relaxedQueryChars

文档地址:https://tomcat.apache.org/tomcat-8.5-doc/config/http.html

<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"
relaxedPathChars="|{}[],"
relaxedQueryChars="|{}[],"
/>

最新文章

  1. kettle中变量的设置和使用介绍
  2. asterisk简单命令
  3. MySql取得日期(前一天、某一天)
  4. android小功能:checkbox使用自己的背景点击切换背景
  5. CUBRID学习笔记 2 安装教程
  6. Android控件之AutoCompleteTextView(自动匹配输入的内容)
  7. C语言二重指针与malloc
  8. 转自 z55250825 的几篇关于FFT的博文(一)
  9. 浙大PTA - - File Transfer
  10. 判断直线与线段相交 POJ 3304 Segments
  11. BZOJ 2463: [中山市选2009]谁能赢呢?(新生必做的水题)
  12. iOS7动态调整文字大小
  13. redis测试实践
  14. P1451 求细胞数量
  15. 微信小程序开发(3) 热门电影
  16. Mysql支持哪几种索引
  17. Ubuntu系统下安装免驱动摄像头
  18. Vue + Bootstrap 制作炫酷个人简历(一)
  19. 阿里云 IOT 对接设备开发 C# 开发设备对接阿里云 IOT平台
  20. python @property使用详解

热门文章

  1. 一周搞定模拟电路P3_电容_记录
  2. JAVA常量池、栈、堆的比较(转载)
  3. LVS、Tomcat、Nginx、PHP优化项
  4. Windows server 2012 R2 服务器用户自动锁定
  5. 「JSOI2013」哈利波特和死亡圣器
  6. Manjaro 安装 ibus-rime 输入法
  7. P1893山峰瞭望
  8. WLC Crash采集什么信息?
  9. Springboot - 更优雅的方式请求发 HTTP 请求
  10. base64相关