【问题标题】:AspNet.Identity.Core : how to create a user manually - HashPasswordAspNet.Identity.Core:如何手动创建用户 - HashPassword
【发布时间】:2020-11-29 21:55:28
【问题描述】:

我有一个 .NET 核心应用程序,它运行良好。

但我需要通过直接插入数据库来创建一批新用户。 现在的问题是,当我尝试登录时,它失败了......

我怀疑散列密码有问题。

我使用以下代码来生成我的哈希和安全标记:

_user.SecurityStamp = Guid.NewGuid().ToString("D");
_user.UserName = _userName;
_user.Email = _email;
var hasher = new Microsoft.AspNetCore.Identity.PasswordHasher<IdentityUser>();
IdentityUser identityUser = new IdentityUser(Guid.Parse(_user.Id), _userName, _email);
_user.PasswordHash = hasher.HashPassword(identityUser, _password);

据我了解,它应该可以工作,但是您有什么想法来调试/修复这个问题吗?

【问题讨论】:

  • 你不需要散列密码(它是自动完成的),除非你有另一个你使用的密码.. 通常你使用 UserManager 使用 CreateAsync() 方法创建一个用户用户及其密码作为参数。所以你也不需要创建一个id。但也许你需要别的东西?
  • 谢谢,但我不使用身份框架。我希望从批处理中直接插入到数据库中。我只需要生成一个正确的哈希值。

标签: asp.net-core .net-core asp.net-identity password-hash


【解决方案1】:

使用

private readonly RandomNumberGenerator _rng;

public virtual string HashPassword(TUser user, string password)
{
    if (_compatibilityMode == PasswordHasherCompatibilityMode.IdentityV2)
    {
        return Convert.ToBase64String(HashPasswordV2(password, _rng));
    }
    else
    {
        return Convert.ToBase64String(HashPasswordV3(password, _rng));
    }
}

参考:https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.identity.passwordhasher-1.hashpassword?view=aspnetcore-3.1

https://github.com/dotnet/aspnetcore/blob/master/src/Identity/Extensions.Core/src/PasswordHasher.cs#L96

阅读更多:https://andrewlock.net/exploring-the-asp-net-core-identity-passwordhasher/#hashing-new-passwords

【讨论】:

  • 谢谢,但这已经是我正在做的事情了,对吧?问题是当我尝试登录时,它失败了!
【解决方案2】:

不要使用自定义的 VerifyHashedPassword 方法。

从下面PasswordHasher的源代码中,我们可以看到VerifyHashedPassword()可以通过数据库中的hashedPassword和原始输入密码自动验证。

using System;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;

namespace Microsoft.AspNet.Identity
{
  internal static class Crypto
  {
    private const int PBKDF2IterCount = 1000;
    private const int PBKDF2SubkeyLength = 32;
    private const int SaltSize = 16;

    public static string HashPassword(string password)
    {
      if (password == null)
        throw new ArgumentNullException("password");
      byte[] salt;
      byte[] bytes;
      using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, 16, 1000))
      {
        salt = rfc2898DeriveBytes.Salt;
        bytes = rfc2898DeriveBytes.GetBytes(32);
      }
      byte[] inArray = new byte[49];
      Buffer.BlockCopy((Array) salt, 0, (Array) inArray, 1, 16);
      Buffer.BlockCopy((Array) bytes, 0, (Array) inArray, 17, 32);
      return Convert.ToBase64String(inArray);
    }

    public static bool VerifyHashedPassword(string hashedPassword, string password)
    {
      if (hashedPassword == null)
        return false;
      if (password == null)
        throw new ArgumentNullException("password");
      byte[] numArray = Convert.FromBase64String(hashedPassword);
      if (numArray.Length != 49 || (int) numArray[0] != 0)
        return false;
      byte[] salt = new byte[16];
      Buffer.BlockCopy((Array) numArray, 1, (Array) salt, 0, 16);
      byte[] a = new byte[32];
      Buffer.BlockCopy((Array) numArray, 17, (Array) a, 0, 32);
      byte[] bytes;
      using (Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt, 1000))
        bytes = rfc2898DeriveBytes.GetBytes(32);
      return Crypto.ByteArraysEqual(a, bytes);
    }

    [MethodImpl(MethodImplOptions.NoOptimization)]
    private static bool ByteArraysEqual(byte[] a, byte[] b)
    {
      if (object.ReferenceEquals((object) a, (object) b))
        return true;
      if (a == null || b == null || a.Length != b.Length)
        return false;
      bool flag = true;
      for (int index = 0; index < a.Length; ++index)
        flag &= (int) a[index] == (int) b[index];
      return flag;
    }
  }
}

测试代码

    public static User user = new User();

    [Route("/")]
    public IActionResult Index()
    {
        //register a user
        if(user != null) {
            //test data
            user.Id = Guid.NewGuid();
            user.UserName = "test";
            user.Email = "test@x.com";
            user.Password = "password";

            var hasher = new Microsoft.AspNetCore.Identity.PasswordHasher<IdentityUser>();
            IdentityUser identityUser = new IdentityUser(user.Id.ToString());

            user.PasswordHash = hasher.HashPassword(identityUser, user.Password);
        }

        //... save user to DB

        return View();
    }

登录控制器

    [HttpPost]
    public IActionResult Login(LoginViewModel login)
    {
        if (ModelState.IsValid)
        {

            //... Here are codes get Id by email from DB

            var hasher = new Microsoft.AspNetCore.Identity.PasswordHasher<IdentityUser>();
            IdentityUser identityUser = new IdentityUser(user.Id.ToString());

            if (PasswordVerificationResult.Failed == hasher.VerifyHashedPassword(identityUser,user.PasswordHash, login.Password))
               ModelState.AddModelError("Password", "password is wrong");

        }
        else
            ModelState.AddModelError("Email", "email or password invalid");

        return PartialView("_LoginModalPartial", login);
    }

结果测试

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-07
    • 2011-06-03
    • 2011-02-20
    • 1970-01-01
    相关资源
    最近更新 更多