IE上的The valid characters are defined in RFC 7230 and RFC 3986坑


前言

參照:https://blog.csdn.net/qq_28165595/article/details/79686681

日常開發中經常遇到一些莫名其妙的小問題,例如即將上線的項目在線上異常報錯,但是在本地確可以正常運行。往往這猝不及防的小驚喜,真是讓我們猿猿欲哭無淚啊。這里簡單總結一下在IE瀏覽器上遇到的一個小坑,之前就因為這個小坑,着實慌了一把。

坑的由來

首先瞅瞅這坑長啥樣子。如下圖所示 

上面的圖片中,我們明確看到這樣一行Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986,這句話的大致意思就是說請求頭中包含了 RFC 7230 and RFC 3986規范中定義的非法字符。在這種情況下就會導致頁面報400異常。 
觸發上面報這種異常的代碼片如下,只是一個簡單的get請求

 

 

接下來我們來看看RFC 3986中到底是怎么規范的

RFC3986文檔規定,Url中只允許包含英文字母(a-zA-Z)、數字(0-9)、-_.~4個特殊字符以及所有保留字符。RFC3986文檔對Url的編解碼問題做出了詳細的建議,指出了哪些字符需要被編碼才不會引起Url語義的轉變,以及對為什么這些字符需要編碼做出了相應的解釋。

US-ASCII字符集中沒有對應的可打印字符:Url中只允許使用可打印字符。US-ASCII碼中的10-7F字節全都表示控制字符,這些字符都不能直接出現在Url中。同時,對於80-FF字節(ISO-8859-1),由於已經超出了US-ACII定義的字節范圍,因此也不可以放在Url中。

保留字符:Url可以划分成若干個組件,協議、主機、路徑等。有一些字符(:/?#[]@)是用作分隔不同組件的。例如:冒號用於分隔協議和主機,/用於分隔主機和路徑,?用於分隔路徑和查詢參數,等等。還有一些字符(!$&’()*+,;=)用於在每個組件中起到分隔作用的,如=用於表示查詢參數中的鍵值對,&符號用於分隔查詢多個鍵值對。當組件中的普通數據包含這些特殊字符時,需要對其進行編碼。

RFC3986中指定了以下字符為保留字符:! * ’ ( ) ; : @ & = + $ , / ? # [ ] 
不安全字符:還有一些字符,當他們直接放在Url中的時候,可能會引起解析程序的歧義。這些字符被視為不安全字符,原因有很多。 
空格:Url在傳輸的過程,或者用戶在排版的過程,或者文本處理程序在處理Url的過程,都有可能引入無關緊要的空格,或者將那些有意義的空格給去掉。 
引號以及<>:引號和尖括號通常用於在普通文本中起到分隔Url的作用 
井號(#) 通常用於表示書簽或者錨點 
%:百分號本身用作對不安全字符進行編碼時使用的特殊字符,因此本身需要編碼 
{}|\^[]`~:某一些網關或者傳輸代理會篡改這些字符

同時RFC 3986規范在tomcat7.0.73版本中就已經提出了,RFC 7230也是對前者的一些補充或者說是完善,所以在tomcat7.0.73及以上版本都會有這種問題。

如何填坑

解決上面問題,有如下幾種思路。

      • 換用低版本的tomcat,既然你是tomcat7.0.73版本,及以上版本有這種問題,我們可以暫時的逃避這個問題,選擇低版本的tomcat。
      • 用post代替get請求,上面也說過了是get請求才會有這種情況,如果方便的話,我們完全可以采用post請求來實現這個功能
      • 在前端對前端URL進行編碼

        下面介紹一下前端對URL進行編碼的實現方法。 
        javascript可以使用的內置函數有

      • encodeURI()
      • encodeURIComponent() 
        他們都是用utf-8的編碼方式,對於get請求,他的編碼格式默認是按照瀏覽器的編碼格式進行編碼的,我們可以設置瀏覽器的編碼格式,但是每個用戶的瀏覽器的編碼格式不可能都是一致的,這樣我們的get請求的參數有時候就會出現亂碼問題,但是如果我們自己在前端對get請求利用encodeURI()或者encodeURIComponent ()來統一設置成utf-8編碼,這樣我們在后台在用utf-8來解碼,就不會出現亂碼問題。 
        這里需要注意的一點,對於get請求的中文亂碼問題,如果你沒有在tomcat配置文件中設置編碼格式,天真的想用request.setCharacterEncoding(“UTF-8”)來在后端設置后端的解碼格式,這種方式對於get請求是無效的。同時有的小伙伴可能會想我們可以在項目的web.xml中設置編碼過濾器。抱歉這種方式對於get請求也是無效的。 
        對於這種情況我們可以采用new String(request.getParameter(“name”).getBytes(“iso-8859-1”),”UTF-8”) 來進行二次編碼解碼過程,這種方式就能解決get請求中文亂碼問題,當然我們也可以在tomcat的配置文件中設置統一編碼格式。
      • <Connector port="8080" protocol="HTTP/1.1" maxThreads="150" connectionTimeout="20000" redirectPort="8443" URIEncoding="utf-8"/>
      • 。。。。。。好像有點扯遠了,回歸主題,接下來我們來看看encodeURI和encodeURIComponent 
        encodeURI(),用來encode整個URL,不會對下列字符進行編碼:+ : / ; ?&。它只會對漢語等特殊字符進行編碼 
        encodeURIComponent (),用來enode URL中想要傳輸的字符串,它會對所有url敏感字符進行encode 
        在對url做encode操作時,一定要根據情況選擇不同的方法。 
        例如url = “testGetRequest/testSimpleGet?name=+’愛琴孩’” 
        此時可以用encodeURI(url) 
        當你的參數中包含+ : / ; ?&請使用 encodeURIComponent 方法對這些參數單獨進行編碼。 
        例如url = “testGetRequest/testSimpleGet?parm=www.baidu.com/ccc/ddd?name=abcd” 
        所以我上面一開始遇到的問題只需要在前端編碼一下就可以解決了

      • 當然你也可以換低版本的tomcat,這里是不提倡的!

        總結:我的個人解決辦法

      • 前端jsp頁面:這里kfname和kfname傳的參數是漢字
      • 前端編碼兩次:

      • 后端解碼一次(或者兩次,我這里解碼一次兩次都可以);
      •  

      • 需要注意的一點,上面這種異常只是在IE上會出現,火狐,360,谷歌上是沒有的。 
        多注意點小細節。。。遠離猝不及防的驚喜。如果對你遇到的問題有所幫助,記得推薦,謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM