編碼規則
URL編碼遵循下列規則: 每對name/value由&;符分開;每對來自表單的name/value由=符分開。如果用
戶沒有輸入值給這個name,那么這個name還是出現,只是無值。任何特殊的字元(就是那些不是簡單的七位ASCII,如漢字)將以百分符%用十六進制編碼,當然也包括象 =,&;,和 % 這些特殊的字元。其實url編碼就是一個字元ascii碼的十六進制。不過稍微有些變動,需要在前面加上“%”。比如“\”,它的ascii碼是92,92的十六進制是5c,所以“\”的url編碼就是%5c。那么漢字的url編碼呢?很簡單,看例子:“胡”的ascii碼是-17670,十六進制是BAFA,url編碼是“%BA%FA”。
URL編碼表
backspace %08 | I %49 | v %76 | ó %D3 |
tab %09 | J %4A | w %77 | Ô %D4 |
linefeed | K %4B | x %78 | Õ %D5 |
creturn %0D | L %4C | y %79 | Ö %D6 |
space %20 | M %4D | z %7A | Ø %D8 |
! %21 | N %4E | { %7B | ù %D9 |
" %22 | O %4F | | %7C | ú %DA |
# %23 | P %50 | } %7D | Û %DB |
$ %24 | Q %51 | ~ %7E | ü %DC |
% %25 | R %52 | ¢ %A2 | Y %DD |
& %26 | S %53 | £ %A3 | T %DE |
' %27 | T %54 | ¥ %A5 | ß %DF |
( %28 | U %55 | | %A6 | à %E0 |
) %29 | V %56 | § %A7 | á %E1 |
* %2A | W %57 | « %AB | a %E2 |
+ %2B | X %58 | ¬ %AC | ã %E3 |
, %2C | Y %59 | ˉ %AD | ä %E4 |
- %2D | Z %5A | o %B0 | å %E5 |
. %2E | [ %5B | ± %B1 | æ %E6 |
/ %2F | \ %5C | a %B2 | ç %E7 |
0 %30 | ] %5D | , %B4 | è %E8 |
1 %31 | ^ %5E | μ %B5 | é %E9 |
2 %32 | _ %5F | » %BB | ê %EA |
3 %33 | ` %60 | ¼ %BC | ë %EB |
4 %34 | a %61 | ½ %BD | ì %EC |
5 %35 | b %62 | ¿ %BF | í %ED |
6 %36 | c %63 | à %C0 | î %EE |
7 %37 | d %64 | á %C1 | ï %EF |
8 %38 | e %65 | Â %C2 | e %F0 |
9 %39 | f %66 | Ã %C3 | ñ %F1 |
: %3A | g %67 | Ä %C4 | ò %F2 |
; %3B | h %68 | Å %C5 | ó %F3 |
< %3C | i %69 | Æ %C6 | ô %F4 |
= %3D | j %6A | Ç %C7 | õ %F5 |
> %3E | k %6B | è %C8 | ö %F6 |
%3F | l %6C | é %C9 | ÷ %F7 |
@ %40 | m %6D | ê %CA | ø %F8 |
A %41 | n %6E | Ë %CB | ù %F9 |
B %42 | o %6F | ì %CC | ú %FA |
C %43 | p %70 | í %CD | û %FB |
D %44 | q %71 | Î %CE | ü %FC |
E %45 | r %72 | Ï %CF | y %FD |
F %46 | s %73 | D %D0 | t %FE |
G %47 | t %74 | Ñ %D1 | ÿ %FF |
H %48 | u %75 | ò %D2 | |
URL編碼防止sql注入
URL編碼平時我們是用不到的,因為IE會自動將你輸入到地址欄的非數字字母轉換為url編碼。或許你已經想起了,有人提出資料庫名字裡帶上“#”以防止被下載,因為IE遇到#就會忽略後面的字母。破解方法很簡單——用url編碼%23替換掉#。現在SQL注射非常流行,所以就有人寫了一些防注射的腳本。當然啦,思路不一樣,效果大不同。下面××SQL通用防注入asp版部分代碼。
Fy_Url=Request.ServerVariables("QUERY_STRING")
Fy_a=split(Fy_Url,"&")
REDIM Fy_Cs(Ubound(Fy_a))
On Error Resume Next
for Fy_x=0 to ubound(Fy_a)
Fy_Cs(Fy_x) = left(Fy_a(Fy_x),instr(Fy_a(Fy_x),"=")-1)
Next
For Fy_x=0 to ubound(Fy_Cs)
If Fy_Cs(Fy_x)<>"" Then
If Instr(lcase(Request(Fy_Cs(Fy_x))),"and")<>0 then
Response.Write "出現錯誤!"
Response.End
End If
End If
Next
它的思路就是先獲得提交的數據,以“&”為分界獲得並處理name/value組,然後判斷value里是否含有定義的關鍵字(這裡為求簡便,我只留下了“and”),有之,則為注射。
乍一看去,value被檢查了,似乎沒有問題。是的,value不會有問題,可是,name呢?
它的name/value組值來自於Request.ServerVariables("QUERY_STRING"),呵呵,不好意思,這裡出問題了。Request.ServerVariables("QUERY_STRING")是得到客戶端提交的字元串,這裡並不會自動轉換url編碼,哈哈,如果我們把name進行url編碼再提交的話,呵呵,那就可以繞過檢查了。比如參數是ph4nt0m=lake2 and lis0,此時程式能夠檢測到;如果提交%50h4nt0m=lake2 and lis0(對p進行url編碼),程式就會去判斷%50h4nt0m的值,而%50h4nt0m會被轉換為ph4nt0m,所以%50h4nt0m值為空,於是就繞過了檢測。為什麼既然name不解碼可以繞過檢查而value就不能繞過呢?因為value的值取自Request(Fy_Cs(Fy_x)),這個伺服器就會解碼的。程式怎么改進呢?只要能夠得到客戶端提交的數據是解碼後的就可以了,把得到name的語句改為For Each SubmitName In Request.QueryString就可以了。
使用舉例
前言
編碼問題是JAVA初學者在web開發過程中經常會遇到問題,其中之一是URL中使用中文等非ASCII的字元造成伺服器後台程式解析出現亂碼的問題。
常見出錯部分
也就是容易出現中文字元的部分:
(1)Query String中的參數值
(2)servlet path
常見出錯原因
(1)瀏覽器:我們的客戶端(瀏覽器)本身並沒有遵循URI編碼的規範。
(2)Servlet伺服器:Servlet伺服器的沒有正確配置。
(3)開發人員並不了解Servlet的規範和API的含義。
servlet規範
(1)HttpServletRequest.setCharacterEncoding()方法 僅僅只適用於設定post提交的requestboda的編碼而不是設定get方法提交的queryString的編碼。該方法告訴套用伺服器應該採用什麼編碼解析post傳過來的內容。
(2) HttpServletRequest.getPathInfo()返回的結果是由Servlet伺服器解碼(decode)過的。
(3) HttpServletRequest.getRequestURI()返回的字元串沒有被Servlet伺服器decoded過。
(4) POST提交的數據是作為request body的一部分。
(5) 網頁的Http頭中ContentType("text/html; charset=GBK")的作用:
(a) 告訴瀏覽器網頁中數據是什麼編碼;
(b) 表單提交時,通常瀏覽器會根據ContentType指定的charset對表單中的數據編碼,然後傳送給伺服器的。
注意:這裡所說的ContentType是指http頭的ContentType,而不是在網頁中mete中的ContentType。