报错报文:
19-Dec-2021 23:55:56.790 信息 [http-nio-8080-exec-8] org.apache.coyote.http11.Http11Processor.service 解析 HTTP 请求 header 错误
Note: further occurrences of HTTP request 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:483)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:502)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:818)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1623)
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)
请求URL:
http://localhost:8080/app-api/exportHistory/getTxt?Auth=bdffdf6da5ff4d65a62d983285c0fb66&id=[20211215114722316533282]
请求方式:
- GET
可能原因:
原因 | 解决 | 检查 |
---|---|---|
请求header参数过长 | 修改maxHttpHeaderSize字段 | 排除 |
不能解析header中的汉字 | 增加URIEncoding=“UTF-8” | 排除 |
浏览器强转成https协议 | 清除浏览器缓存 | 排除 |
springboot内置tomcat版本与部署时tomcat版本冲突 | 去除tomcat启动依赖 | 排除 |
header含不可解析的字符符号 | properties及xml中修改配置 | 确认 |
-
请求header参数过长,缓冲区大小不够
Tomcat的header缓冲区大小不够,需要在server.xml中增加maxHttpHeaderSize字段,具体设置在service.xml文件中设置maxHttpHeaderSize=“你想要的大小”
<Connector port="8080" protocol="HTTP/1.1"
maxHttpHeaderSize="10240000"
connectionTimeout="20000"
redirectPort="8443"/>
-
不能解析header中的汉字
需要在server.xml中增加 URIEncoding="UTF-8"配置
<Connector port="8080" protocol="HTTP/1.1"
maxHttpHeaderSize="10240000"
connectionTimeout="20000"
redirectPort="8443" URIEncoding="UTF-8"/>
-
浏览器强转成https协议
chrome浏览器清空缓存
-
springboot内置tomcat版本与部署时tomcat版本冲突
如果要将最终的打包形式改为war的话,还需要对pom.xml文件进行修改,因为spring-boot-starter-web中包含内嵌的tomcat容器,所以直接部署在外部容器会冲突报错。解决方案如下:
- 去除内嵌的spring-boot-starter-tomcat依赖
- 增加tomcat-embed-jasper依赖(scope必须是provided)
Markdown将文本转换为 HTML。
因为SpringBootServletInitializer需要依赖
javax.servlet,而tomcat-embed-jasper下面的tomcat-embed-core中就有这个javax.servlet,如果没用provided,最终打好的war里面会有servlet-api这个jar,这样就会跟tomcat本身的冲突了
pom 依赖修改:
<dependency>
<groupId>net.riking</groupId>
<artifactId>web-html-core</artifactId>
<version>2.4.0</version>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!--添加provided -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
- header含不可解析的字符符号
-
在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个属性,可以接收任意特殊字符的组合,根据需要可以自行增减。
server.xml:
<Connector port="8080" protocol="HTTP/1.1" maxHttpHeaderSize="10240000" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" relaxedPathChars="|{}[]," relaxedQueryChars="|{}[],"/>
catalina.properties:
tomcat.util.buf.StringCache.byte.enabled=true #tomcat.util.buf.StringCache.char.enabled=true #tomcat.util.buf.StringCache.trainThreshold=500000 #tomcat.util.buf.StringCache.cacheSize=5000 #This system property is deprecated. Use the relaxedPathChars relaxedQueryChars #attributes of the Connector instead. These attributes permit a wider range of #characters to be configured as valid. #Allow for changes to HTTP request validation #WARNING: Using this option may expose the server to CVE-2016-6816 #tomcat.util.http.parser.HttpParser.requestTargetAllow=|{}[] #tomcat.util.http.parser.HttpParser.requestTargetAllow=|{}?& tomcat.util.http.parser.HttpParser.requestTargetAllow=|{} org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true