在编写前端接口MD5加密的时候出现一个问题,前端如何更改,始终与后台的MD5加密不同,最后发现是因为汉字问题。
网上找了很多解决方案都不行,看到有一个人说利用另类编码加密,然后再进行MD5加密可以完成。我利用这个思路,首先肯定想到用BASE64先给字符串编码,发现JSON字符串JSBASE64编码无法正常使用,然后又想到用encodeURI()来实现,最后发现它不编码的字符太多,所以又改成encodeURIComponent().不过它不编码的字符也挺多,当前检查他对双引号,反斜杠,空格影响最大,我在MD5加密前先给取消掉。后面可能还会出现其他字符,暂时先处理这几个。
具体代码如下
//JS代码
GetSignature: function (userid, timestamp, nonce, data, token) {
//拼接签名数据
var signStr = (timestamp + '') + (nonce + '') + userid + token + data;
//将字符串中字符按升序排序
var sortStr = Array.from(signStr).sort().join("");//升序
//console.log(Array.from(signStr).sort().reverse().join(""));//降序
sortStr = sortStr.replace(/\"/g, "");//去掉"
sortStr = sortStr.replace(/[\\]/g, "");//去掉\
sortStr = sortStr.replace(/\s/g, "");//去掉空格
sortStr = encodeURIComponent(sortStr);//encodeURIComponent编码避免汉字
sortStr = sortStr.toUpperCase();//全部转换成大写
//使用MD5加密
var md5Val = hex_md5(sortStr);
return md5Val
},
发现JSencodeURIComponent汉字是大写字母,但是C#编码后都是小写,为了防止MD5加密因为大小写不同,所有将两方同时更改为大写。
/// <summary>
/// 后台C#代码
/// </summary>
/// <param name="timeStamp">时间戳</param>
/// <param name="nonce">随机数</param>
/// <param name="userId">用户ID</param>
/// <param name="jsonData">参数Json</param>
/// <param name="signature">传入的签名</param>
/// <returns></returns>
private static bool GetSignature(string timeStamp, string nonce, string userId, string signtoken, string jsonData, string signature)
{
var md5 = System.Security.Cryptography.MD5.Create();
//拼接签名数据
var signStr = timeStamp + nonce + userId + signtoken + jsonData;
//将字符串中字符按升序排序
var sortStr = string.Concat(signStr.OrderBy(c => c));
sortStr= sortStr.Replace("\"", "");//去掉"
sortStr = sortStr.Replace("\\", "");//去掉\
sortStr = sortStr.Replace(" ", "");//去掉空格
sortStr = HttpUtility.UrlEncode(sortStr); //避免汉字
sortStr = sortStr.ToUpper();//全部转换成大写
//需要将字符串转成字节数组
byte[] buffer = Encoding.Default.GetBytes(sortStr);
//使用MD5加密
var md5Val = md5.ComputeHash(buffer);
//把二进制转化为小写的32进制
StringBuilder result = new StringBuilder();
foreach (var c in md5Val)
{
result.Append(c.ToString("X2"));
}
string strSignature = result.ToString().ToLower();
if (strSignature == signature)
{
return true;
}
else
{
return false;
}
}
顺便补充一下C#加解码知识
HttpUtility.UrlEncode(text); //utf-8 编码
HttpUtility.UrlDecode(text); //utf-8 解码
HttpUtility.UrlEncode(text, System.Text.Encoding.GetEncoding(936)); //gb2312编码
HttpUtility.UrlDecode(text, System.Text.Encoding.GetEncoding(936)); //gb2312解码
JS加解密知识
encodeURI不编码字符有82个:!,#,$,&,’,(,),,+,,,-,.,/,:,;,=,?,@,_,~,0-9,a-z,A-Z
encodeURIComponent不编码字符有71个:!, ',(,),,-,.,_,~,0-9,a-z,A-Z