base64 parameter encryption and decryption

 

The problem of passing base64 encoded parameters through URL, and its solution java code

In general, the parameters in the URL should use the url encoding rules, that is, all non-alphanumeric characters in the parameter string except -_. will be replaced by a percent sign (%) followed by two hexadecimal digits number, spaces are encoded as plus signs (+). But for parameters with Chinese, this encoding will make the encoded string very long. If you want to encode parameters in a shorter way, you can use base64 encoding to encode strings, but base64 encoding cannot handle Chinese in JavaScript, because Chinese in JavaScript is stored in UTF-16. And base64 can only handle single-byte characters, so you cannot directly use base64 to encode JavaScript strings with Chinese characters. However, the UTF-16 encoded Chinese can be converted into UTF-8 by  utf16to8  provided in the utf.js program, and then base64 encoded. The encoded string can be directly decoded into UTF-8 Chinese string through base64_decode after being passed to the server. But there is another problem to be aware of. The plus sign (+) is used in base64 encoding, and + will be treated as a space when the URL is passed, so the plus sign in the base64 encoded string must be replaced with %2B before it can be passed as a URL parameter. Otherwise there will be an error after decoding on the server side.

It turned out that when  the JavaScript client implementation of PHPRPC 1.1 was written, it was because I didn't notice this problem, so when passing Chinese parameters, sometimes the passed parameters were correct, and sometimes the parameters were wrong when decoding on the server side. It took a lot of effort to find out that this was the problem.

Code:

/**
 * base64 encoding tool class
 * @author wanggang
 * @version 2010-12-31
 */
public class Base64Util {

    /**
     *  将 s 进行 BASE64 编码
     * @param s
     * @return
     */
    public static String encode(byte[] s) {
        if (s == null)
            return null;
        return (new sun.misc.BASE64Encoder()).encode(s);
    }

    /**
     * BASE64 encoding s, encoding for url
     * @param s
     * @return
     */
    public static String encodeForUrl(byte[] s){
        if (s == null)
            return null;
        String standerBase64 = encode(s );        
        String encodeForUrl = standerBase64;
        //Convert to base64 encoding for url
        encodeForUrl = encodeForUrl.replace("=", "");
        encodeForUrl = encodeForUrl.replace("+", "*");
        encodeForUrl = encodeForUrl.replace ("/", "-");
        //Remove line
        breaks encodeForUrl = encodeForUrl.replace("\n", "");
        encodeForUrl = encodeForUrl.replace("\r", "");
        
        //Convert * to -x-
        //Prevent characters that violate the protocol
        encodeForUrl = encodeSpecialLetter1(encodeForUrl);
       
        return encodeForUrl;
        
    }
    
    /**
     * Convert * to -x-,
                 in order to prevent characters that violate the protocol, convert -x to -xx
     * @param str
     * @return
     */
    private static String encodeSpecialLetter1 (String str){
     str = str.replace("-x", "-xx");
     str = str.replace("*", "-x-");
     return str;
    }
    
    /**
     * Convert -x -sign is *, -xx is converted to -x
     * @param str
     * @return
     */
    private static String decodeSpecialLetter1(String str){
     str = str.replace("-x-", "*");
  str = str. replace("-xx", "-x");
     return str;
    }
    /**
     * BASE64 encode
     s * @param s
     * @return
     */
    public static String encode(String s) {
        
        if (s == null)
            return null;
        return encode(s.getBytes());
    }

    /**将 BASE64 编码的字符串 s 进行解码
     * 
     * @param s
     * @return
     */
    public static byte[] decode(String s) {
        if (s == null)
            return null;
        sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
        try {
            byte[] b = decoder.decodeBuffer(s);
            return b;
        } catch (Exception e) {
            return null;
        }
    }
    /**将 BASE64 编码的字符串 s 进行解码
     * 
     * @param s
     * @return
     */
    public static byte[] decodeForUrl(String s) {
        if (s == null)
            return null;
        s = decodeSpecialLetter1(s);
        s = s.replace("*", "+");
        s = s.replace("-", "/");
        s += "=";
        sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
        try {
            byte[] b = decoder.decodeBuffer(s );
            return b;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        
        String a = "将 s 进行 BASE64 编码,针对url的编码将 s 进行 BASE64 编码,针对url的编码将 s 进行 BASE64 编码,针对url的编码将 s 进行 BASE64 编码,针对url的编码将 s 进行 BASE64 编码,针对url的编码将 s 进行 BASE64 编码,针对url的编码将 s 进行 BASE64 编码,针对url的编码将 s 进行 BASE64 编码,针对url的编码将 s 进行 BASE64 编码,针对url的编码将 s 进行 BASE64 编码,针对url的编码userId=1441&mailId=981&date=2011-02-15-62";
        String b = encodeForUrl(a.getBytes());
//        b = b.replace("\n", "");
//        b = b.replace("\r", "");
        System.out.println(b);
        
        
        System.out.println(new String(decodeForUrl(b)));
        
        b = encode(a.getBytes());
        System.out.println(b);
        System.out.println(new String(decode(b)));

    }

}

 

 

 

 

 

 

 

为什么需要对参数进行编码?相信有过开发的经验的广大程序员都知道,在Web中,若是直接在Url地址上传递参数值,若是中文,或者+等什么的就会出现乱码现象,若是数字或者英文的好象没有什么问题,简言之,传递过来的参数是需要进行编码的。
在这里,也许有人会说,为什么不直接用Server.UrlDecode和Server.UrlEncode这两个来进行编码和解码的操作呢?

的确,这两个服务器端对象很好使用,用起来也很方便,但是,若在客户端是HTML的Input,查询的时候页面是HTML或者其他的,反正不是.NET的,那这个对象还可以用吗?


我现在就遇到这样的问题,查询的东东放在页面,而且那个页面我根本不想让他是.aspx结尾的,哈,感觉HTML的挺不错,而且里面的控件也是用HTML对象的。

下面先来看两个函数,UTF16转UTF8和UTF8转Utf16的。
function utf16to8(str) {
    var out, i, len, c;

    out = "";
    len = str.length;
    for(i = 0; i < len; i++) {
 c = str.charCodeAt(i);
 if ((c >= 0x0001) && (c <= 0x007F)) {
     out += str.charAt(i);
 } else if (c > 0x07FF) {
     out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
     out += String.fromCharCode(0x80 | ((c >>  6) & 0x3F));
     out += String.fromCharCode(0x80 | ((c >>  0) & 0x3F));
 } else {
     out += String.fromCharCode(0xC0 | ((c >>  6) & 0x1F));
     out += String.fromCharCode(0x80 | ((c >>  0) & 0x3F));
 }
    }
    return out;
}

function utf8to16(str) {
    var out, i, len, c;
    var char2, char3;

    out = "";
    len = str.length;
    i = 0;
    while(i < len) {
 c = str.charCodeAt(i++);
 switch(c >> 4)
 { 
   case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
     // 0xxxxxxx
     out += str.charAt(i-1);
     break;
   case 12: case 13:
     // 110x xxxx   10xx xxxx
     char2 = str.charCodeAt(i++);
     out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
     break;
   case 14:
     // 1110 xxxx  10xx xxxx  10xx xxxx
     char2 = str.charCodeAt(i++);
     char3 = str.charCodeAt(i++);
     out += String.fromCharCode(((c & 0x0F) << 12) |
        ((char2 & 0x3F) << 6) |
        ((char3 & 0x3F) << 0));
     break;
 }
    }

    return out;
}

那么为什么需要进行转化呢?因为在JavaScript中获得的中文字符是用UTF16进行编码的,和我们统一的页面标准格式UTF-8可不一样哦,所以需要先进行转化,上面的函数UTF-16到UTF8,然后再进行Base64的编码。

下面是关于Js进行Base64编码和解码的相关操作:

var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var base64DecodeChars = new Array(
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
    -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);
//客户端Base64编码
function base64encode(str) {
    var out, i, len;
    var c1, c2, c3;

    len = str.length;
    i = 0;
    out = "";
    while(i < len) {
 c1 = str.charCodeAt(i++) & 0xff;
 if(i == len)
 {
     out += base64EncodeChars.charAt(c1 >> 2);
     out += base64EncodeChars.charAt((c1 & 0x3) << 4);
     out += "==";
     break;
 }
 c2 = str.charCodeAt(i++);
 if(i == len)
 {
     out += base64EncodeChars.charAt(c1 >> 2);
     out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
     out += base64EncodeChars.charAt((c2 & 0xF) << 2);
     out += "=";
     break;
 }
 c3 = str.charCodeAt(i++);
 out += base64EncodeChars.charAt(c1 >> 2);
 out += base64EncodeChars.charAt(((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4));
 out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6));
 out += base64EncodeChars.charAt(c3 & 0x3F);
    }
    return out;
}
//客户端Base64解码
function base64decode(str) {
    var c1, c2, c3, c4;
    var i, len, out;

    len = str.length;
    i = 0;
    out = "";
    while(i < len) {
 /* c1 */
 do {
     c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
 } while(i < len && c1 == -1);
 if(c1 == -1)
     break;

 /* c2 */
 do {
     c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
 } while(i < len && c2 == -1);
 if(c2 == -1)
     break;

 out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));

 /* c3 */
 do {
     c3 = str.charCodeAt(i++) & 0xff;
     if(c3 == 61)
  return out;
     c3 = base64DecodeChars[c3];
 } while(i < len && c3 == -1);
 if(c3 == -1)
     break;

 out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));

 /* c4 */
 do {
     c4 = str.charCodeAt(i++) & 0xff;
     if(c4 == 61)
  return out;
     c4 = base64DecodeChars[c4];
 } while(i < len && c4 == -1);
 if(c4 == -1)
     break;
 out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
    }
    return out;
}

这样传递过去的值就可以在服务器端解码操作了。
下面是C#的Base64加码和解码的相关类:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

namespace CNVP.Base64
{
    /// <summary>
    /// MyBase64 的摘要说明
    /// </summary>
    public class MyBase64
    {
        public MyBase64()
        {
            //
            // TODO: 在此处添加构造函数逻辑
            //
        }
        /// <summary>
        /// 服务器端Base64编码
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public string base64Encode(string data)
        {
            try
            {
                byte[] encData_byte = new byte[data.Length];
                encData_byte = System.Text.Encoding.UTF8.GetBytes(data);
                string encodedData = Convert.ToBase64String(encData_byte);
                return encodedData;
            }
            catch (Exception e)
            {
                throw new Exception("Error in base64Encode" + e.Message);
            }
        }
        /// <summary>
        /// 服务器端Base64解码
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public string base64Decode(string data)
        {
            try
            {
                System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding();
                System.Text.Decoder utf8Decode = encoder.GetDecoder();
                byte[] todecode_byte = Convert.FromBase64String(data);
                int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
                char[] decoded_char = new char[charCount];
                utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0);
                string result = new String(decoded_char);
                return result;
            }
            catch (Exception e)
            {
                throw new Exception("Error in base64Decode" + e.Message);
            }
        }
    }
}


        var Keyword=base64encode(utf16to8(document.all.Keyword.value));
        Keyword=Keyword.replace("+","%2B");//替换+,否则在服务器解码的时候会出错
 
服务器端使用以下代码调用:
            CNVP.Base64.MyBase64 base64 = new CNVP.Base64.MyBase64();
            Keyword=base64.base64Decode(Keyword);

 

 

 

http://www.360doc.com/content/11/0609/22/1542811_122788158.shtml

 

 

http://www.cnblogs.com/Apollo/archive/2006/04/15/376083.html

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326728839&siteId=291194637