当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > 彻底解决ASP.NET MD5加密中文结果和ASP不一致的问题

ASP.NET
FreeTextBox(版本3.1.6)在ASP.Net 2.0中使用方法
.NET 常用功能和代码小结
在 .NET Framework 2.0 中未处理的异常导致基于 ASP.NET 的应用程序意外退出
asp.net IList查询数据后格式化数据再绑定控件
asp.net sql存储过程
asp.net 简单实现禁用或启用页面中的某一类型的控件
asp.net(c#)获取内容第一张图片地址的函数
The remote procedure call failed and did not execute的解决办法
ASP.NET 在线文件管理
asp.net 读取并修改config文件实现代码
ASP.NET Cookie 操作实现
asp.net Silverlight中的模式窗体
Silverlight中动态获取Web Service地址
asp.net Silverlight应用程序中获取载体aspx页面参数
asp.net 水晶报表隔行换色实现方法
asp.net 获取Gridview隐藏列的值
手动把asp.net的类生成dll文件的方法
asp.net 使用ObjectDataSource控件在ASP.NET中实现Ajax真分页
动态指定任意类型的ObjectDataSource对象的查询参数
asp.net Md5的用法小结

彻底解决ASP.NET MD5加密中文结果和ASP不一致的问题


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-13   浏览: 78 ::
收藏到网摘: n/a

ASP.NET MD5加密中文结果和ASP不一致的问题的解决方法 当要进行MD5加密的字符串不含中文时,那么ASP.NET的加密结果和ASP是一致的:
复制代码 代码如下:

Response.Write(FormsAuthentication.HashPasswordForStoringInConfigFile("www.mzwu.com", "MD5"));
//结果:D66E1F138689B9B5AA4C520D9EAFFB61

复制代码 代码如下:

Response.Write(MD5("www.mzwu.com",32))
'结果:d66e1f138689b9b5aa4c520d9eaffb61

当要进行MD5加密的字符串含中文时,两者的加密结果就不一致了:
复制代码 代码如下:

Response.Write(FormsAuthentication.HashPasswordForStoringInConfigFile("木子屋", "MD5"));
//结果:34D9CBD5164C47058DFA3AF832E2D1DC

复制代码 代码如下:

Response.Write(MD5("木子屋",32))
'结果:0a40a90190da023ae7aa17771663a41e

我们知道,ASP.NET默认使用utf-8编码格式,而ASP使用的是gb2312编码格式,正是由于这编码格式不同,才导致了两者对中文加密结果的不同。下边我们看看怎么让ASP.NET的编码结果和ASP一样,那也就意味着要让ASP.NET采用gb2312编码格式,这点FormsAuthentication.HashPasswordForStoringInConfigFile()方法是办不到的,我们得使用System.Security.Cryptography.MD5CryptoServiceProvider对象的ComputeHash方法来进行加密:
复制代码 代码如下:

MD5CryptoServiceProvider MD5 = new MD5CryptoServiceProvider();
Response.Write(BitConverter.ToString(MD5.ComputeHash(Encoding.GetEncoding("gb2312").GetBytes("木子屋"))).Replace("-", ""));
//结果:0A40A90190DA023AE7AA17771663A41E

若要再使用utf-8加密也非常容易:
复制代码 代码如下:

MD5CryptoServiceProvider MD5 = new MD5CryptoServiceProvider();
Response.Write(BitConverter.ToString(MD5.ComputeHash(Encoding.GetEncoding("utf-8").GetBytes("木子屋"))).Replace("-", ""));
//结果:34D9CBD5164C47058DFA3AF832E2D1DC

问题似乎是比较完美的解决了,我们再来完善一下:当要加密的字符串是从其他页面传进来时,其他页面采用的编码格式可能是gb2312,可能是utf-8,还可能是其他的编码格式,怎么解决呢?你可能会觉得很简单啊,使用它先前的编码格式进行加密不就行了?实际测试中你会发现两个很严重的问题:
1. 我们无从知道参数传过来时是使用什么编码格式;
2. 如果两个页面使用的编码方式不一样,那么Request接收到的参数值会乱码,那就不要谈加密了;
  问题1比较好解决,要求对方传参数的同时必须多加一个参数说明采用的编码格式,问题2的解决方法是不使用Request直接接收参数值,废话不多说了,看下边的函数:
复制代码 代码如下:

/**//// <summary>
/// 对字符串进行MD5加密
/// </summary>
/// <param name="text">要加密的字符串</param>
/// <param name="charset">字符串编码格式</param>
/// <example>str = MD5("木子屋","gb2312");</example>
/// <returns></returns>
public string MD5(string text, string charset)
{
    return (MD5(text, charset, false));
}
/**//// <summary>
/// 对字符串或参数值进行MD5加密
/// </summary>
/// <param name="text">要加密的字符串或参数名称</param>
/// <param name="charset">字符串编码格式</param>
/// <param name="isArg">加密字符串类型 true:参数值 false:字符串</param>
/// <returns></returns>
public string MD5(string text, string charset, bool isArg)
{
    try
    {
        MD5CryptoServiceProvider MD5 = new MD5CryptoServiceProvider();
        if (isArg)
        {
            NameValueCollection Collect = HttpUtility.ParseQueryString(Request.Url.Query, Encoding.GetEncoding(charset));//使用Collect接收参数值
            if (Collect[text] != null)
            {
                return BitConverter.ToString(MD5.ComputeHash(Encoding.GetEncoding(charset).GetBytes(Collect[text].ToString()))).Replace("-", "");
            }
        }
        else
        {
            return BitConverter.ToString(MD5.ComputeHash(Encoding.GetEncoding(charset).GetBytes(text))).Replace("-", "");
        }
    }
    catch { }
    return string.Empty;
}

说明1:上边代码需要引入的命名空间
复制代码 代码如下:

using System.Text;
using System.Web.Security;
using System.Security.Cryptography;
using System.Collections.Specialized;

说明2:32位密文如何转化成16位?
16位密文是32位密文的9到24位字符。如:"0a40a90190da023ae7aa17771663a41e"→"90da023ae7aa1777"