将passwordFormat从Encrypted更改为Hashed

时间:2011-02-09 18:19:07

标签: asp.net passwords asp.net-membership

我发现很少有关于将现有数据库从加密密码转换为哈希密码的信息。 (我能够找到关于转换另一种方式的更多信息,但它没有多大帮助。)

正如大多数人所知,更改web.config中的passwordFormat设置只会影响新用户。我有一个包含几百个用户的数据库,我想将它们转换为使用散列密码而不更改现有密码。

是否还有其他人熟悉如何处理这个问题?感谢您的任何提示。

4 个答案:

答案 0 :(得分:14)

Greg的解决方案是一个良好的开端,但它不会影响现有用户。 SqlMembershipProvider通过在表中存储PasswordFormat(0 = clear,1 = Hashed,2 = Encrypted)以及密码来保护现有用户和密码。更改提供程序密码格式仅影响对用户表的插入。要将现有用户的密码转换为Hashed,您必须更改每个条目的PasswordFormat参数。这是一种简单的方法:

void HashAllPasswords()
{
    var clearProvider = Membership.Providers["SqlProvider_Clear"];
    var hashedProvider = Membership.Providers["SqlProvider_Hashed"];
    int dontCare;
    if (clearProvider == null || hashedProvider == null) return;
    var passwords = clearProvider.GetAllUsers(0, int.MaxValue, out dontCare)
        .Cast<MembershipUser>().ToDictionary(u => u.UserName, u => u.GetPassword());

    using (var conn = new SqlConnection(
           ConfigurationManager.ConnectionStrings[0].ConnectionString))
    {
        conn.Open();
        using (var cmd = new SqlCommand(
               "UPDATE [aspnet_Membership] SET [PasswordFormat]=1", conn))
            cmd.ExecuteNonQuery();
    }

    foreach (var entry in passwords)
    {
        var resetPassword = hashedProvider.ResetPassword(entry.Key, null);
        hashedProvider.ChangePassword(entry.Key, resetPassword, entry.Value);
    }
}

答案 1 :(得分:12)

这是我开始的方法,看看我有多远:

  1. 在我的web.config中创建两个MembershipProviders,一个用于加密密码,另一个用于哈希。
  2. 使用加密密码提供程序遍历所有用户。 (SqlMembershipProvider.GetAllUsers
  3. 使用加密密码提供程序获取用户密码。 (MembershipUser.GetPassword
  4. 使用散列密码提供程序将用户密码更改为相同的密码。 (MembershipUser.ChangePassword
  5. 所以它是这样的:

        <membership defaultProvider="HashedProvider">
            <providers>
                <clear />
                <add name="HashedProvider" connectionStringName="MembershipConnectionString" enablePasswordRetrieval="false"  requiresQuestionAndAnswer="false" applicationName="MyApp" passwordFormat="Hashed"  type="System.Web.Security.SqlMembershipProvider" />
                <add name="EncryptedProvider" connectionStringName="MembershipConnectionString" enablePasswordRetrieval="true" requiresQuestionAndAnswer="false" applicationName="MyApp" passwordFormat="Encrypted" type="System.Web.Security.SqlMembershipProvider" />
            </providers>
        </membership>
    

    代码:

    SqlMembershipProvider hashedProvider = (SqlMembershipProvider)Membership.Providers["HashedProvider"];
    SqlMembershipProvider encryptedProvider = (SqlMembershipProvider)Membership.Providers["EncryptedProvider"];
    
    int unimportant;
    foreach (MembershipUser user in encryptedProvider.GetAllUsers(0, Int32.MaxValue, out unimportant ))
    {
        hashedProvider.ChangePassword(user.UserName, user.GetPassword(), user.GetPassword());
    }
    

答案 2 :(得分:1)

出于安全考虑,在数据库中从加密密码切换到哈希绝对是正确的决定。

通常,要从现有的加密密码中创建哈希值,首先应解密它们然后对它们进行哈希处理。请注意,您将丢失(当您最终切换时)原始密码。相反,您将拥有用户密码的唯一指纹(哈希)。

还要考虑使用salt进行散列(防御rainbow tables等),并查看慢速哈希算法,例如BCryptCodeplex&amp; Article: How To Safely Store A Password )出于安全原因而不是像MD5这样的快速原因。

还要记住,将来更换散列算法比将其从ecryption更改为hash更加省力。所以你想第一次就做好;)

答案 3 :(得分:0)

我会提醒你不要随意散列你的密码,因为这种方法有很多警告。这Blog post about hashing passwords对我非常有洞察力,我认为你应该阅读它。为什么要使用散列密码而不是加密?