C#在與java對接時候的UrlEncode的坑 C# url編碼
阿新 • • 發佈:2020-08-06
最近與建行介面做對接和與一家簡訊運營商做對接時候遇到了這個坑
在java中對UrlEncode 時候哪些url非安全字元被轉為%數字和大寫字幕組合,比如:zhangsan/d 會被轉為zhangsan%2Fd ,而在C#中確被轉為zhangsan%2fd 。注意大小寫的差異
然後就導致了各種加密驗籤無法通過的情況。
於是就自己在C#原來的UrlEncode的基礎上寫了一個UrlEncode方法
/// <summary> /// Url編碼 /// </summary> /// <param name="str">原字串</param>/// <param name="encoding">編碼格式</param> /// <param name="upper">特殊字元編碼為大寫</param> /// <returns></returns> static string UrlEncode(string str, Encoding encoding) { if (encoding == null) { encoding= UTF8Encoding.UTF8; } byte[] bytes = encoding.GetBytes(str); int num = 0; int num2 = 0; for (int i = 0; i < bytes.Length; i++) { char ch = (char)bytes[i]; if (ch == ' ') { num++; } else if (!IsUrlSafeChar(ch)) { num2++; //非url安全字元 } } if (num == 0 && num2 == 0) { return str; //不包含空格和特殊字元 } byte[] buffer = new byte[bytes.Length + (num2 * 2)]; //包含特殊字元,每個特殊字元轉為3個字元,所以長度+2x int num3 = 0; for (int j = 0; j < bytes.Length; j++) { byte num6 = bytes[j]; char ch2 = (char)num6; if (IsUrlSafeChar(ch2)) { buffer[num3++] = num6; } else if (ch2 == ' ') { buffer[num3++] = 0x2B; //0x2B代表 ascii碼中的+,url編碼時候會把空格編寫為+ } else { //特殊符號轉換 buffer[num3++] = 0x25; //代表 % buffer[num3++] = (byte)IntToHex((num6 >> 4) & 15); //8位向右移動四位後 與 1111按位與 ,即保留高前四位 ,比如 /為 2f,則結果保留了2 buffer[num3++] = (byte)IntToHex(num6 & 15); //8位 ,與00001111按位與,即保留 後四位 ,比如 /為2f,則結果保留了 f } } return encoding.GetString(buffer); } static bool IsUrlSafeChar(char ch) { if ((((ch < 'a') || (ch > 'z')) && ((ch < 'A') || (ch > 'Z'))) && ((ch < '0') || (ch > '9'))) { switch (ch) { case '(': case ')': case '*': case '-': case '.': case '!': break; //安全字元 case '+': case ',': return false; //非安全字元 default: //非安全字元 if (ch != '_') { return false; } break; } } return true; } static char IntToHex(int n) //n為0-f { if (n <= 9) { return (char)(n + 0x30); //0x30 十進位制是48 對應ASCII碼是0 } return (char)((n - 10) + 0x41); //0x41 十進位制是 65 對應ASCII碼是A }