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

7

我正在将数万名用户从没有在数据库中存储密码的旧网站迁移到这个新的网络应用程序,但是当我尝试使用异步方法导入用户时,它最终需要几天的时间,以至于我只能在几天后取消它。

现在,我只能直接从_context.Users.Add创建新用户并分配其角色,这一点我可以轻松完成。 但是,我似乎无法找出如何创建通用密码(所有用户的密码相同),因为这些用户只需获得观看直播的密码(不需要超级安全),但是对于处理客户端/管理端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();

有人能帮我解决如何将密码哈希化以存储到数据库中的问题吗?

3个回答

13
如果用户登录,我将自动为他们输入默认密码。 如果您正在使用.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)
{

}

身份验证系统将帮助创建密码哈希并存储在数据库中。如果您仍需要手动哈希密码,请参见IPasswordHasher接口

编辑:

如果您想通过数据库上下文直接插入/更新数据,您需要设置正确的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();

我似乎没有能力将密码作为CreateAsync的参数输入。它要求ApplicationUser和CancellationToken。 - Alex Liosatos
我有一个来自AccountManager的CreateUserAsync方法。问题在于,此方法完成所需的时间非常长。特别是对于超过100,000个帐户。它似乎每半秒或一秒钟创建一个帐户。 - Alex Liosatos
1
@AlexLiosatos,请查看更新的回复并检查它是否有帮助。 - Nan Yu
@AlexLiosatos 我使用“await userManager.CreateAsync(applicationUser, "Test123!");”(以及“userManager.AddClaimsAsync”)在3.5至4分钟内创建了1000个应用程序用户。我在一个循环中生成了applicationUser,其SubjectId为“TestSubjectId”+索引,Name为“TestName” +索引和一些声明。 - SergSam
如果您创建一个控制台应用程序并直接在数据库中添加用户(当然,您需要在应用程序中添加适当的Nuget包,例如Microsoft.AspNetCore.Identity等),则可以在几分钟内创建数千个用户。 - undead10
显示剩余2条评论

2
作为补充,如果您只想更新给定用户的密码字段:

最初的回答

var oldUser = await _userManager.GetUserAsync(User);

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

对于问题“我应该如何哈希一个密码?”,你可以像这样使用UserManager引用的PasswordHasher来哈希已注册用户的密码:

最初的回答:

使用UserManager引用的PasswordHasher,您可以像这样哈希已注册用户的密码:

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

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接