2022年2月9日 星期三

UrlEncode() 特殊字元注意事項

最近在處理一段特殊的程式邏輯,原本以為兩個相同字串經過 UrlEncode(),再透過某個加密演算法

(如:DES或AES )後,內容應該會是一樣,畢竟是相同字串,但透過比對後,發現竟然不是這樣,

這其中貓膩究竟是甚麼呢...



先來說說原始的字串,是一個 json 內文,類似像這樣

 {"name":"Test","age":1}


另外這段文字,分別使用 JavaScript 與C# 內建的函式對這段文字 UrlEncode,以下是編碼後的狀況


JavaScript:encodeURI(json)

結果:"%7B%22name%22:%22Test%22,%22age%22:1%7D"


C#:HttpUtility.UrlEncode(json)

結果:"%7b%22name%22%3a%22Test%22%2c%22age%22%3a1%7d"


以上兩者的UrlEncode 很明顯從外觀可以看出差異,其中

  • 「{」

    • JS:%7B

    • C#:%7b

  • 「:」

    • JS:保留不動

    • C#:3a

  • 「,」

    • JS:保留不動

    • C#:2c

  • 「}」

    • JS:%7D

    • C#:%7d


雖然兩者Encode 後產出的字串,表面上有所差異,但若經過C# HttpUtility.UrlDecode()

都是可以解碼回原本的字串,如下操作



所以,其實若沒有將UrlEncode 後的結果做後續應用,應該不會有甚麼大問題;假設,現需要

將兩者編碼後的結果做其中一種可逆加密計算如 AES


「%7B%22name%22:%22Test%22,%22age%22:1%7D」 加密:

結果:a+CTFrJtU1/oG3nCBJ0NX5WVLcb9eexRvjE80sa9DdNLJg4B8RM8x/OTmbgnNMX2


「%7b%22name%22%3a%22Test%22%2c%22age%22%3a1%7d」 加密:

結果:Fc9zPyete4mb1u1AkUtl4CcHozJ+2GCuh1WAqdqPzKJBYziEhwxRCBNznpB4dZM6



由以上結果很明顯可看出差異



回到最初的問題,為何都是 UrlEncode 兩者產出的值會不同?參考微軟,說明

space (空白)會被轉換成 +,而< and > 會被轉換成 %3c and %3e


但是「{」「}」與「,」並沒有交代,難保其他沒有被列舉的符號其實也是會被置換,真是傷腦筋,

文章下方有說明,建議使用 WebUtility 類別


WebUtility 類別是在 System.Net Namespace 底下,以下直接使用

結果


由以上可以發現,其 UrlEncode 產出的值與 JavsScript 產出的結果一致


但有點美中不足的是 WebUtility.UrlEncode() 函式僅在 .net framework 4.5 以上才支援,可惜 ~ 

所幸,天公疼惜,找到黑大這篇,這邊黑哥是遇到UrlEncode 後空白變+號的狀況,

其中,文末有提到可使用 「Uri.EscapeDataString() 」



而Decode 可以使用「Uri.UnescapeDataString(value)」




完美結案..


參考


沒有留言:

張貼留言