Членство в ASP.Net сохраняет измененный пароль в виде обычного текста даже при установленном формате хэшированного пароля

Я использую ASP.Net SqlMembershipProvider для управления моими пользователями. Вот мой конфиг:


            
                
                
            
        

Моя проблема заключается в следующем: когда я вызываю Membership.CreateUser для создания новых пользователей, пароль хранится в БД в хешированном формате с солью - и это все хорошо. Однако, когда я вызываю Membership.ChangePassword в функции администратора, он сохраняет пароль в текстовом формате. Я действительно не могу понять это поведение, так как конфиг ясно говорит:Hashed» и создание нового пользователя создает хешированный пароль.

Ответы на вопрос(3)

Решение Вопроса

ChangePassword() Метод поставщика ASPMembership по умолчанию, формат пароля для существующего пользователя извлекается из базы данных и является форматом, используемым для кодирования нового пароля для существующего пользователя, а не форматом пароля, который установлен вweb.config, который теперь может указывать другой формат для использования. Вы можете убедиться в этом самизагрузка исходного кода для поставщиков по умолчанию.

Мой вопрос в том, хранится ли пароль в виде открытого текста для пользователя, у которого уже был пароль, сохраненный в виде открытого текста? Вы можете легко это проверить, проверив значение поля PasswordFormat для пользователя в таблице.aspnet_Membership, Значения:

Clear = 0,
Hashed = 1,
Encrypted = 2,

РЕДАКТИРОВАТЬ :

если вам нужно хешировать пароли самостоятельно, код фреймворка может пригодиться

// generate a salt
public string GenerateSalt()
{
    byte[] buf = new byte[16];
    (new RNGCryptoServiceProvider()).GetBytes(buf);
    return Convert.ToBase64String(buf);
}

// hashes the password, using the supplied salt
public string HashPassword(string pass, string salt)
{
    byte[] bIn = Encoding.Unicode.GetBytes(pass);
    byte[] bSalt = Convert.FromBase64String(salt);
    byte[] bAll = new byte[bSalt.Length + bIn.Length];
    byte[] bRet = null;

    Buffer.BlockCopy(bSalt, 0, bAll, 0, bSalt.Length);
    Buffer.BlockCopy(bIn, 0, bAll, bSalt.Length, bIn.Length);

    // this assumes a Hashed password (PasswordFormat = 1)
    HashAlgorithm s = HashAlgorithm.Create( Membership.HashAlgorithmType );
    bRet = s.ComputeHash(bAll);

    return Convert.ToBase64String(bRet);
}

теперь вам просто нужно извлечь все записи из базы данных, где PasswordFormat = 0, запустить их через консольное приложение, чтобы хэшировать пароль и сохранить соль, хешированный пароль в базу данных, а также обновить поле PasswordFormat до 1

 Scott Rippey05 янв. 2012 г., 23:42
Итак, как можно это исправить программно?
 Scott Rippey06 янв. 2012 г., 02:08
@RussCam Wow, спасибо за немедленный ответ! Я пришел к такому же точному выводу ... спасибо за предоставление исходного кода.
 Russ Cam06 янв. 2012 г., 00:52
@ScottRippey Вы имеете в виду, как вы хэшируете пароли тех пользователей, которые уже существуют и могут иметь пароль, сохраненный в виде открытого текста? Если так, то естьНасколько я знаю, нет автоматического способа сделать это; вам нужно будет извлечь все пользовательские записи из базы данных со значением поля PasswordFormat, равным 0, выполнить каждую из них через код для генерации соли для каждого пароля и использовать ее для хеширования пароля, а затем сохранить каждую в базе данных и обновить PasswordFormat одновременно
 Russ Cam09 нояб. 2009 г., 21:46
Нет проблем - я нахожу странным, что это поведение по умолчанию. Это'Очень просто написать собственного провайдера, а затем реализовать форматирование пароля именно так, как вы хотите
 Ben09 нояб. 2009 г., 21:12
Русь тыты чемпион !!! Это будет проблемой - яЯ тестирую это на пользователях, которые я изначально установил вручную в БД с четкими паролями. Большое спасибо за совет :)

Решение, вероятно, работает, но естьЭто более простой способ, если все ваши существующие пользователи имеют либо открытые, либо зашифрованные пароли. Установите в своем web.config 2 провайдера членства в sql, один из которых использует чистые (или зашифрованные) пароли, а другой - хэшированные. Затем выполните этот код где-нибудь в вашем веб-приложении:

void ConvertPasswordsToHashed()
{
    var clearProvider = Membership.Providers["SqlProvider"];
    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);
    }
}
</membershipuser>

PasswordFormat вaspnet_Membership Таблица. Затем я изменяю пароль на тот же с помощьюResetPassword а такжеChangePassword методы. Также, если пользователь был заблокирован, я разблокирую его перед сменой пароля, а затем снова блокирую. В файле app.config у меня есть строки подключения для модели базы данных и поставщика членства, а также определение поставщика членства.

Обратите внимание, что если старый пароль не соответствует вашим последним требованиям к паролю в настройках провайдера, тоChangePassword метод потерпит неудачу.

Код следующий:

static void Main(string[] args)
{
    using (var db = new MyEntities())
    {
        var usersToFix = db.aspnet_Membership.Where(x => x.PasswordFormat == 0).ToList();

        foreach (var userToFix in usersToFix)
        {
            userToFix.PasswordFormat = 1;

            var password = userToFix.Password;
            var passwordQuestion = userToFix.PasswordQuestion;
            var passwordAnswer = userToFix.PasswordAnswer;
            var lastLockoutDate = userToFix.LastLockoutDate;

            db.SaveChanges();


            var user = Membership.GetUser(userToFix.UserId);
            bool locked = user.IsLockedOut;

            if (locked)
            {
                user.UnlockUser();
            }

            var resetPassword = user.ResetPassword();
            user.ChangePassword(resetPassword, password);
            user.ChangePasswordQuestionAndAnswer(password, passwordQuestion, passwordAnswer);

            if (locked)
            {
                userToFix.IsLockedOut = true;
                userToFix.LastLockoutDate = lastLockoutDate;
                db.SaveChanges();
            }

            Console.WriteLine("{0} - OK", user.UserName);
        }
    }


    Console.WriteLine("Done!");
    Console.ReadKey();
}
 granadaCoder18 июн. 2015 г., 23:16
Мне не хватало   var resetPassword = user.ResetPassword (); user.ChangePassword (resetPassword, пароль); "  трюк. Спасибо

Ваш ответ на вопрос