Asp.net

將密碼格式從加密更改為散列

  • March 15, 2012

我發現關於將現有數據庫從加密密碼轉換為散列密碼的資訊非常少。(我能夠找到更多關於轉換另一種方式的資訊,但這並沒有太大幫助。)

大多數人都知道,更改passwordFormatweb.config 中的設置只會影響新使用者。我有一個有幾百個使用者的數據庫,我想將它們轉換為使用散列密碼而不更改那些現有的密碼。

有沒有其他人熟悉如何處理這個問題?感謝您的任何提示。

這是我開始的方法,看看我能走多遠:

  1. 在我的 web.config 中創建兩個 MembershipProvider,一個用於加密密碼,一個用於散列。
  2. 使用加密密碼提供程序遍歷所有使用者。( SqlMembershipProvider.GetAllUsers )
  3. 使用加密密碼提供程序獲取使用者密碼。( MembershipUser.GetPassword )
  4. 使用散列密碼提供程序將使用者的密碼更改為相同的密碼。( MembershipUser.ChangePassword )

所以它會是這樣的:

   <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());
}

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);
   }
}

引用自:https://stackoverflow.com/questions/4948824