一. 錯誤描述
公司由於受外部軟件的限制, 暫時只能使用 IE8, IE8大家都知道, 對標準的 W3C的支持不是很好, 兼容性容易出現問題
系統是在 Tomcat7中發佈, Tomcat8中開發的
錯誤代碼
十月 21, 2019 5:02:47 下午 org.apache.coyote.http11.AbstractHttp11Processor process
信息: 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.AbstractNioInputBuffer.parseRequestLine(AbstractNioInputBuffer.java:285)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1045)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:684)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1539)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1495)
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:745)
二. 原因分析
這個問題是高版本tomcat中的新特性:就是嚴格按照 RFC 3986規範進行訪問解析,而 RFC 3986規範定義了Url中只允許包含英文字母(a-zA-Z)、數字(0-9)、-_.~4個特殊字符以及所有保留字符(RFC3986中指定了以下字符爲保留字符:! * ’ ( ) ; : @ & = + $ , / ? # [ ])。而我們的系統在通過地址傳參時,在url中傳了一段json,傳入的參數中有"{"不在RFC3986中的保留字段中,所以會報這個錯。
根據(https://bz.apache.org/bugzilla/show_bug.cgi?id=60594) ,從以下版本開始,有配置項能夠關閉/配置這個行爲:
8.5.x系列的:8.5.12 onwards
8.0.x系列的:8.0.42 onwards
7.0.x系列的:7.0.76 onwards
三.處理方法
(1)使用Tomcat7.0.69之前的版本
(2)對url的特殊字符進行轉義
1、escape 和 unescape
2、encodeURI 和 decodeURI
3、encodeURIComponent 和 decodeURIComponent
(3)修改tomcat配置文件
在conf/catalina.properties 中添加 tomcat.util.http.parser.HttpParser.requestTargetAllow=|{}
注意中文的問題
四.js對url進行編碼和解碼(三種方式區別)
URL: 只有 0-9[a-Z] $ - _ . + ! * ' ( ) , 以及某些保留字,才能不經過編碼直接用於 URL。
例如:搜索的中文關鍵字,複製網址之後再粘貼就會發現該URL已經被轉碼。
1、escape 和 unescape
原理:對除ASCII字母、數字、標點符號 @ * _ + - . / 以外的其他字符進行編碼。
編碼:escape('http://www.baidu.com?name=zhang@xiao@jie&order=1')
結果:"http%3A//www.baidu.com%3Fname%3Dzhang@xiao@jie%26order%3D1"
編碼:escape('張')
結果:"%u5F20"
解碼:unescape("http%3A//www.baidu.com%3Fname%3Dzhang@xiao@jie%26order%3D1")
結果:"http://www.baidu.com?name=zhang@xiao@jie&order=1"
編碼:unescape("%u5F20")
結果:"張"
2、encodeURI 和 decodeURI
原理:返回編碼爲有效的統一資源標識符 (URI) 的字符串,不會被編碼的字符:! @ # $ & * ( ) = : / ; ? + '
encodeURI()是Javascript中真正用來對URL編碼的函數。
編碼:encodeURI('http://www.baidu.com?name=zhang@xiao@jie&order=1')
結果:"http://www.baidu.com?name=zhang@xiao@jie&order=1"
解碼:decodeURI("http%3A//www.baidu.com%3Fname%3Dzhang@xiao@jie%26order%3D1")
結果:"http%3A//www.baidu.com%3Fname%3Dzhang@xiao@jie%26order%3D1"
3、encodeURIComponent 和 decodeURIComponent
原理:對URL的組成部分進行個別編碼,而不用於對整個URL進行編碼
編碼:encodeURIComponent('http://www.baidu.com?name=zhang@xiao@jie&order=1')
結果:"http%3A%2F%2Fwww.baidu.com%3Fname%3Dzhang%40xiao%40jie%26order%3D1"
解碼:decodeURIComponent("http%3A%2F%2Fwww.baidu.com%3Fname%3Dzhang%40xiao%40jie%26order%3D1")
結果:"http://www.baidu.com?name=zhang@xiao@jie&order=1"
encodeURI() 函數和encodeURIComponent()函數的區別:前者只對中文部分轉碼和部分不能解析特殊字符編碼,後者還會對encodeURI() 不能轉移的字符串轉義。範圍 encodeURI() 小於 encodeURIComponent(), 對url解析建議採用 encodeURI() 。
// 參考: https://www.cnblogs.com/z-one/p/6542955.html