如何使用 Asp.Net Core 2.2 / IdentityServer4 / SP.NET Core Identity 手动散列密码

How to manually hash a password using Asp.Net Core 2.2 / IdentityServer4 / SP.NET Core Identity

我正在将数以万计的用户从数据库中没有密码的旧网站迁移到这个新的 Web 应用程序,但是,当我尝试使用异步方法导入用户时,它结束了花了几天时间,几天后我就取消了它。

现在我已经求助于直接从 _context.Users.Add 创建新用户并分配他们的角色,我可以毫无问题地做到这一点。但是,我似乎无法弄清楚如何创建一个通用的密码(所有相同的密码),因为这些用户将只获得一个密码来查看直播(不需要超级安全),但我仍然需要通过 [= 处理其他内容的管理员帐户的安全部分23=]边UI。如果用户登录,我会让它自动为他们输入默认密码。

但出于某种原因,我无法让密码哈希器正常工作,因为当我登录时,它说密码错误...

这就是我用来生成密码和创建用户的...

 var appUser = new ApplicationUser() {
  Id = GenerateId(),
   AccessFailedCount = 0,
   Email = user[1],
   PasswordHash = "",
   FullName = "Standard User",
   UserName = user[1],
   PhoneNumber = user[8],
   FirstName = user[2],
   LastName = user[3],
   JoinMailingList = user[4],
   Country = user[5],
   City = user[6],
   StateRegion = user[7]
 };

 _context.Users.Add(appUser);

 var options = new PasswordHasherOptions();
 options.CompatibilityMode = PasswordHasherCompatibilityMode.IdentityV2;

 var hasher = new PasswordHasher < ApplicationUser > ();
 appUser.PasswordHash = hasher.HashPassword(appUser, "Default8!");

 var role = _context.Roles.FirstOrDefault(r => r.Name == "user");

 if (role != null) {
  var userRole = new IdentityUserRole < string > ();
  userRole.RoleId = role.Id;
  userRole.UserId = appUser.Id;
  _context.UserRoles.Add(userRole);
 }
}

_context.SaveChanges();

任何人都可以帮助我解决如何将密码哈希存储到数据库中的问题吗?

If a user signs in, I will have it automatically enter the default password for them.

如果您使用的是 .net core Identity,您可以使用 UserManager.CreateAsync 使用给定密码在后备存储中创建指定用户:

public virtual System.Threading.Tasks.Task<Microsoft.AspNetCore.Identity.IdentityResult> CreateAsync (TUser user, string password);

以下代码供您参考:

var user = new ApplicationUser { UserName = "wx2@hotmail.com", Email = "wx2@hotmail.com" };
var result = await _userManager.CreateAsync(user, "YourPassWord");
if (result.Succeeded)
{

}

身份系统将帮助创建密码哈希并将其存储在数据库中。如果您仍然需要手动散列密码,请参阅


编辑:

如果您想通过数据库上下文直接 insert/update,您应该设置正确的 NormalizedUserNameSecurityStamp 以使系统正常工作:

ApplicationUser applicationUser = new ApplicationUser();
Guid guid = Guid.NewGuid();
applicationUser.Id = guid.ToString();
applicationUser.UserName = "wx@hotmail.com";
applicationUser.Email = "wx@hotmail.com";
applicationUser.NormalizedUserName = "wx@hotmail.com";

_context.Users.Add(applicationUser);


var hasedPassword = _passwordHasher.HashPassword(applicationUser, "YourPassword");
applicationUser.SecurityStamp = Guid.NewGuid().ToString();
applicationUser.PasswordHash = hasedPassword;

_context.SaveChanges();

另外,如果您只想更新给定用户的密码字段:

var oldUser = await _userManager.GetUserAsync(User);

var result = await _userManager.ChangePasswordAsync(oldUser,
                    updateUserVm.CurrentPassword,
                    updateUserVm.NewPassword);

以及问题 "How I'm supposed to Hash a password?" 的示例。您可以像这样使用 UserManager-Referenced PasswordHasher 对注册的用户密码进行哈希处理:

ApplicationUser user = _userManager.Users...;
user.PasswordHash = _userManager.PasswordHasher.HashPassword(user, newPassword);

我根据 .net6 PasswordHasher 文档最新版本 (V3) 在这个 Whosebug 答案中编写了我的 class PasswordHasher: