C#在與java對接時候的UrlEncode的坑

最近與建行接口做對接和與一家短信運營商做對接時候遇到了這個坑

在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 
        }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章