標籤:

URL編碼

為什麼需要URL編碼

通常如果一樣東西需要編碼,說明這樣東西並不適合傳輸。原因多種多樣,如Size過大,包含隱私數據,對於Url來說,之所以要進行編碼,是因為Url中有些字元會引起歧義

例如Url參數字元串中使用key=value鍵值對這樣的形式來傳參,鍵值對之間以&符號分隔,如/s?q=abc& ie=utf-8。如果你的value字元串中包含了=或者&,那麼勢必會造成接收Url的伺服器解析錯誤,因此必須將引起歧義的&和= 符號進行轉義,也就是對其進行編碼。

又如,Url的編碼格式採用的是ASCII碼,而不是Unicode,這也就是說你不能在Url中包含任何非ASCII字元,例如中文。否則如果客戶端瀏覽器和服務端瀏覽器支持的字符集不同的情況下,中文可能會造成問題。

Url編碼的原則就是使用安全的字元(沒有特殊用途或者特殊意義的可列印字元)去表示那些不安全的字元。

Url中只允許包含英文字母(a-zA-Z)、數字(0-9)、-_.~4個特殊字元以及所有保留字元。

URL中對非法字元進行編碼

Url編碼通常也被稱為百分號編碼(Url Encoding,also known as percent-encoding),是因為它的編碼方式非常簡單,使用%百分號加上兩位的字元——0123456789ABCDEF——代表一個位元組的 十六進位形式。Url編碼默認使用的字符集是US-ASCII。例如a在US-ASCII碼中對應的位元組是0x61,那麼Url編碼之後得到的就 是%61,我們在地址欄上輸入Google,實際上就等同於在google上搜索abc了。又如@符號 在ASCII字符集中對應的位元組為0x40,經過Url編碼之後得到的是%40。

對於非ASCII字元,需要使用ASCII字符集的超集進行編碼得到相應的位元組,然後對每個位元組執行百分號編碼。 對於Unicode字元,RFC文檔建議使用utf-8對其進行編碼得到相應的位元組,然後對每個位元組執行百分號編碼。如「中文」使用UTF-8字符集得到 的位元組為0xE4 0xB8 0xAD 0xE6 0x96 0x87,經過Url編碼之後得到「%E4%B8%AD%E6%96%87」。

如果某個位元組對應著ASCII字符集中的某個非保留字元,則此位元組無需使用百分號表示。 例如「Url編碼」,使用UTF-8編碼得到的位元組是0x55 0x72 0x6C 0xE7 0xBC 0x96 0xE7 0xA0 0x81,由於前三個位元組對應著ASCII中的非保留字元「Url」,因此這三個位元組可以用非保留字元「Url」表示。最終的Url編碼可以簡化成 「Url%E7%BC%96%E7%A0%81」 ,當然,如果你用"%55%72%6C%E7%BC%96%E7%A0%81」也是可以的。

Javascript中的escape,encodeURI和encodeURIComponent的區別

Javascript中提供了3對函數用來對Url編碼以得到合法的Url,它們分別是escape / unescape,encodeURI / decodeURI和encodeURIComponent / decodeURIComponent。由於解碼和編碼的過程是可逆的,因此這裡只解釋編碼的過程。

這三個編碼的函數——escape,encodeURI,encodeURIComponent——都是用於將不安全不合法的Url字元轉換為合法的Url字元表示,它們有以下幾個不同點。

對Unicode字元的編碼方式不同

這三個函數對於ASCII字元的編碼方式相同,均是使用百分號+兩位十六進位字元來表示。但是對於Unicode字元,escape的編碼方式是%uxxxx,其中的xxxx是用來表示unicode字元的4位十六進位字元。這種方式已經被W3C廢棄了。但是在ECMA-262標準中仍然保留著escape的這種編碼語法。encodeURI和encodeURIComponent則使用UTF-8對非ASCII字元進行編碼,然後再進行百分號編碼。這是RFC推薦的。因此建議儘可能的使用這兩個函數替代escape進行編碼。

另外,很多HTTP監視工具或者瀏覽器地址欄等在顯示Url的時候會自動將Url進行一次解碼(使用UTF-8字符集),這就是為什麼當你在 Firefox中訪問Google搜索中文的時候,地址欄顯示的Url包含中文的緣故。但實際上發送給服務端的原始Url還是經過編碼的。你可以在地址欄 上使用Javascript訪問location.href就可以看出來了。在研究Url編解碼的時候千萬別被這些假象給迷惑了。

推薦閱讀:

TAG:信息安全 |