C# Asp.Net核心标识,更新现有纯文本密码

C# Asp.Net核心标识,更新现有纯文本密码,c#,asp.net-core,passwords,asp.net-identity,C#,Asp.net Core,Passwords,Asp.net Identity,我们定制了Asp.Net Core以使用我们的学生表,而不是AspNetUser表。对新生来说一切都很顺利。但我们需要更新现有学生的密码。当学生登录时,我想这样做(在AccountControllerLogin方法中),或者这可以一次性完成 [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task<IActionResult> Login(LoginViewModel model, string

我们定制了Asp.Net Core以使用我们的学生表,而不是AspNetUser表。对新生来说一切都很顺利。但我们需要更新现有学生的密码。当学生登录时,我想这样做(在
AccountController
Login
方法中),或者这可以一次性完成

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
{
    ViewData["ReturnUrl"] = returnUrl;
    if (ModelState.IsValid)
    {
        // Require the user to have a confirmed email before they can log on.
        var user = await _userManager.FindByEmailAsync(model.Email);
        if (user != null)
        {
            if (user.PasswordHash == null)
            {
                user.EmailConfirmed = true;
                user.UserName = model.Email;
                user.NormalizedEmail = model.Email.ToUpper();
                user.NormalizedUserName = user.NormalizedEmail;
                //user.PasswordHash = ?;
                //user.SecurityStamp = ?;
                //update user in database.
            }
            //continue on with login process
        }
    }
}
您会发现,您可以为用户设置密码。虽然您可以直接使用内部密码哈希器,但通过用户管理器可以确保用户实体正确更新了密码。因此,您可以依靠用户管理器“做正确的事情”

如果用户没有密码,可以使用设置密码:

var user = await _userManager.FindByEmailAsync(model.Email);
if (user != null && !(await _userManager.HasPasswordAsync(user)))
{
    // retrieve plaintext password
    var originalPassword = GetPlainTextPassword(user);

    var result = await _userManager.AddPasswordAsync(user, originalPassword);

    if (!result.Succeeded)
    {
        // handle error
    }
}
否则,您还可以使用密码重置流生成一个令牌,然后立即使用该令牌重置用户的密码(实际上不涉及用户)。所以你基本上是连锁经营。当然,这只能出于维护原因:

var user = await _userManager.FindByEmailAsync(model.Email);
if (user != null)
{
    // retrieve plaintext password
    var originalPassword = GetPlainTextPassword(user);

    // retrieve token
    var resetToken = await _userManager.GeneratePasswordResetTokenAsync(user);

    // reset password
    var result = await _userManager.ResetPasswordAsync(user, resetToken, originalPassword);

    if (!result.Succeeded)
    {
        // handle error
    }
}


尽管如此,我仍然建议您主动要求用户自行重置密码。只需从数据库中删除纯文本密码,并保留空密码。这样,用户将必须首先重置密码(您应该添加一条说明,说明他们必须在首次登录之前重置密码),并且任何人都无法以纯文本形式查看他们的新密码旧密码暴露在数据库中,可能(希望是?!)有大量备份,即使您认为您的系统是安全的,也可能不是完美的。还有一些人可以访问数据库,并可以直接或间接地向他人公开这些密码(无论是否出于好意)。你不应该足够信任你的系统,以至于不会出任何问题。用户不必相信你能保证他们的密码安全。您应该告诉他们创建一个新密码,并尽早摆脱旧密码。

当密码散列明显为
null
时,用户应该如何登录?那么用户将使用什么密码,您将如何检查它是否是实际用户?为什么不锁定所有应更改其密码的用户,然后解释他们需要使用“忘记密码”链接请求新密码?这样,Identity将生成一个密码重置令牌,用户可以使用该令牌正确设置自己的密码。学生将使用纯文本密码登录。如果我有一个电子邮件和密码匹配,我知道它是一个授权用户,至少在过去的水平此代码在您到达Identity system检查密码散列的点之前。如果我能做到这一点,那么更改对用户来说将是完全透明的。那么您只需重新使用以纯文本形式存储的现有密码?(a) 那你为什么不一次性转换所有密码,而不让用户先登录呢?(b) 无论如何,这是个糟糕的主意。如果您以前将密码存储为纯文本,则绝对应该要求用户更改其密码并仅加密存储新密码。纯文本密码会被破坏,用户应该知道它们是以纯文本形式暴露的,因此他们会永远避免这些密码。当然,这可以一次性完成,但是,人们仍然需要知道如何做到这一点,以便它产生与身份系统可以使用的相同的哈希和安全戳。由于数据库没有被入侵,我们使用SSL,我认为他们没有被暴露。客户正在尝试做正确的事情。如果你有这个问题的答案,我很想看看。谢谢。我想这会管用的。另外,你让我相信用户明确地重置了他们的密码。此外,我们还可以提高对更强密码的要求。
var user = await _userManager.FindByEmailAsync(model.Email);
if (user != null)
{
    // retrieve plaintext password
    var originalPassword = GetPlainTextPassword(user);

    // retrieve token
    var resetToken = await _userManager.GeneratePasswordResetTokenAsync(user);

    // reset password
    var result = await _userManager.ResetPasswordAsync(user, resetToken, originalPassword);

    if (!result.Succeeded)
    {
        // handle error
    }
}