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

Posted

技术标签:

【中文标题】如何使用 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 【发布时间】:2019-09-13 02:55:12 【问题描述】:

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

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

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

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

 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();

谁能帮我解决我应该如何散列密码以存储到数据库中?

【问题讨论】:

【参考方案1】:

如果用户登录,我会让它自动为他们输入默认密码。

如果您使用 .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 interface。


编辑:

如果你想通过数据库上下文直接插入/更新,你应该设置正确的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。 我有一个来自 AccountManager 的 CreateUserAsync。问题是这种方法需要很长时间才能完成。特别是对于超过 10 万个帐户。它似乎在半秒或秒内创建了一个帐户。 @AlexLiosatos ,查看更新回复并检查是否有帮助。 @AlexLiosatos 我用了 3.5 到 4 分钟的时间用“await userManager.CreateAsync(applicationUser, "Test123!");" 创建了 1000 个应用程序用户(和“userManager.AddClaimsAsync”)。我在 for 循环中使用 SubjectId "TestSubjectId" + 索引、Name "TestName" + 索引和一些 Claimes 生成了 applicationUser。 使用 DbContext 对于 1000 个用户大约需要 26 秒,最后使用 DbContext 和 addRange 花了我大约 12 秒,但没有添加声明。像 NanYu 说的那样使用 DbContext,它很有帮助!【参考方案2】:

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

var oldUser = await _userManager.GetUserAsync(User);

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

还有一个问题“我应该如何散列密码?”的示例。您可以像这样使用 UserManager-Referenced PasswordHasher 散列注册的用户密码:

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

【讨论】:

以上是关于如何使用 Asp.Net Core 2.2 / IdentityServer4 / SP.NET Core Identity 手动散列密码的主要内容,如果未能解决你的问题,请参考以下文章

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

如何在启用 ASP.NET Core 2.2 EndpointRouting 的情况下使用 RouteDataRequestCultureProvider?

这是如何使用 Entity Framework Core 和 ASP.NET Core MVC 2.2+ 和 3.0 创建数据传输对象 (DTO)

如何使用 C# 和 ASP.Net Core 2.2 连接和收听外部 websocket url

如何使用 Visual Studio 2019 在 ASP.NET Core 2.2 中安装 Font Awesome [关闭]

Asp.Net Core 2.2 - 如何在使用两个 AuthorizationSchemes、JWT 和 cookie 时返回当前用户 ID