百分號編碼又叫做URL編碼,是一種編碼機制,只要用於URI(包含URL和URN)編碼中。
URL中那些字符需要編碼,又為什么進行編碼
一、URL是什么?
URL(Uniform Resource Locator),統一資源定位符,是地址的別名。包含了關於文件儲存位置和瀏覽器應該如何處理他的信息。互聯網上的每一個文件都有唯一的URL。
URL分為三個部分:
第一部分模式;
第二部分文件所在的主機名稱
第三部分路徑(目錄+文件名)
一般來說,URL只能使用英文字母、阿拉伯數字和某些標點符號,不能使用其他的文字和符號
URL只能使用 ASCII 字符集來通過網絡進行發送。由於URL經常包含ASCII 碼之外的字符,所以必須將 URL 轉換為有效的ASCII 碼的格式。
URL編碼通常會使用 % 后面跟隨兩個十六進制數字來替換 非ASCII 字符;
URL不能包含空格。所以進行編碼時經常使用 + 來替換空格;
二、為什么使用百分號編碼(URL編碼)
為什么會需要編碼?
那是因為這樣東西不適合傳輸。原因可能有很多種:大小過大,包含隱私數據。對於URL而言,之所以進行編碼是因為URL中有一些字符會引起歧義。
例如:URL參數字符串中使用鍵值對這樣的形式來傳參,鍵值對之間使用了 & 符號分隔。
如果value字符串中包含了 @ 或 & 等字符,那么一定會造成接收URL的服務器解析錯誤,因此就需要對造成歧義的 @ 和 & 進行轉義,對其進行編碼。
還有,如果URL的字符集使用的ASCII 碼,不是 Unicode,這就意味着不可以在 URL 中包含任何的非 ASCII 碼,例如:中文,否則客戶端瀏覽器和服務器設定的字符集不同的情況下,輸入的中文就會出現亂碼。
百分號編碼(URL編碼)會對URL不允許出現的字符或者其他特殊情況的允許的字符進行編碼,對於被編碼的字符,最終會轉為百分號 % 開頭,后面跟這昂個十六進制數字的形式。例如:空格(SP)是不允許的字符,在ACSII碼中對應的的二進制值是 00100000 ,最終轉換為 %20。
URL編碼的原則就是使用安全的字符(沒有特殊用途或者特殊意義的可打印字符)去掉那些不安全的字符,以保證內容的正常顯示。
三、需要編碼的字符
RFC3986文檔中規定,URL中只需要包含英文字母(a~zA~Z)、數字(0~9)、(- _ . ~)四個特殊字符以及所有保留字符。
URL經常包含ASCII 碼之外的字符,所以必須將 URL 轉換為有效的ASCII 碼的格式。
有一些字符需要經過編碼才不會引起URL語義的轉變
US-ASCII字符集中沒有對應的可打印字符
Url中只允許使用可打印字符。US-ASCII碼中的10-7F字節全都表示控制字符,這些字符都不能直接出現在Url中。同時,對於80-FF字節(ISO-8859-1),由於已經超出了US-ACII定義的字節范圍,因此也不可以放在Url中。
保留字符
只有字母和數字[0-9 a-z A-Z]、一些特殊符號"$ - _ . + ! * '(),"[不包括雙引號]、以及某些保留字,才可以不經過編碼直接用於URL。
URL 可以划分為若干個 組件、協議、主機、路徑等。有一些字符(: / ? # [ ] @)用以分隔不同的組件。
例如:冒號(:)用於分隔協議和主機;
斜線(/)用於分隔主機和路徑;
問號(?)同於分隔路徑和查詢參數;
還有一些字符(! $ & ' () * + , ; =)用於在每個組件中起到分隔作用的。
例如:等號(=)用於表示查詢參數中的鍵值對;
and符(&)用於分隔查詢多個鍵值對;
當組件中的普通數據包含這些特殊字符的時候,就需要對其進行編碼。
(一)保留字符
Url可以划分成若干個組件,協議、主機、路徑等。有一些字符(:/?#[]@)是用作分隔不同組件的。例如:冒號用於分隔協議和主機,/用於分隔主機和路徑,?用於分隔路徑和查詢參數,等等。還有一些字符(!$&'()*+,;=)用於在每個組件中起到分隔作用的,如=用於表示查詢參數中的鍵值對,&符號用於分隔查詢多個鍵值對。當組件中的普通數據包含這些特殊字符時,需要對其進行編碼。
RFC3986中指定了以下字符為保留字符:

(二)不安全字符
還有一些字符,當他們直接放在Url中的時候,可能會引起解析程序的歧義。這些字符被視為不安全字符,原因有很多。
| 空格 | Url在傳輸的過程,或者用戶在排版的過程,或者文本處理程序在處理Url的過程,都有可能引入無關緊要的空格,或者將那些有意義的空格給去掉 |
| 引號以及<> | 引號和尖括號通常用於在普通文本中起到分隔Url的作用 |
| # | 通常用於表示書簽或者錨點 |
| % | 百分號本身用作對不安全字符進行編碼時使用的特殊字符,因此本身需要編碼 |
| {}|\^[]`~ | 某一些網關或者傳輸代理會篡改這些字符 |
對於Url中的合法字符,編碼和不編碼是等價的,但是對於上面提到的字符,如果不經過編碼,很有可能會造成Url語義的不同。
因此對於Url而言,只有普通英文字符和數字,特殊結構字符 $-_.+!*'()還有保留字符,才能出現在未經過編碼的Url中。
其他字符均需要經過編碼之后才能出現在Url中。
但是由於歷史原因,目前尚存在一些不標准的編碼實現。例如對於~符號,雖然RFC3986文檔規定,對於波浪符號~,不需要進行Url編碼,但是還是有很多老的
關或者傳輸代理會
四、如何對Url中的非法字符進行編碼
Url編碼通常也被稱為百分號編碼(Url Encoding,also known as percent-encoding),是因為它的編碼方式非常簡單,使用%百分號加上兩位的字符——0123456789ABCDEF——代表一個字節的十六進制形式。Url編碼默認使用的字符集是US-ASCII。例如a在US-ASCII碼中對應的字節是0x61,那么Url編碼之后得到的就是%61,我們在地址欄上輸入http://g.cn/search?q=%61%62%63,實際上就等同於在google上搜索abc了。又如@符號在ASCII字符集中對應的字節為0x40,經過Url編碼之后得到的是%40。
常見字符的Url編碼列表:
| ! | * | " | ' | ( | ) | ; | : | @ | & |
%21 |
%2A |
%22 |
%27 |
%28 |
%29 |
%3B |
%3A |
%40 |
%26 |
| = | + | $ | , | / | ? | % | # | [ | ] |
%3D |
%2B |
%24 |
%2C |
%2F |
%3F |
%25 |
%23 |
%5B |
%5D |
對於非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”也是可以的。
由於歷史的原因,有一些Url編碼實現並不完全遵循這樣的原則
參考博客:http://www.cnblogs.com/ECJTUACM-873284962/
