asp.net-core - ASP.NET Core Identity - 扩展密码哈希器

标签 asp.net-core asp.net-core-mvc asp.net-identity-3

我正在努力将应用程序从 Web 表单迁移到 MVC,并选择使用 ASP.NET Core 来使用 MVC 6。

在我当前的应用程序中,我有一个与身份一起使用的自定义密码哈希器。在我的自定义 UserManager 类中,实现非常简单:

public ApplicationUserManager()
  : base(new UserStore<IdentityUser>(new AuthContext()))
{
    this.PasswordHasher = new SqlPasswordHasher();
}

我正在尝试对 .NET Core 执行相同的操作,但 UserManager 中不存在 PasswordHasher 属性。我看到构造函数将采用 IPasswordHasher 参数,因此我尝试了以下方法:

public ApplicationUserManager(IUserStore<ApplicationUser> store, IOptions<IdentityOptions> optionsAccessor,
        IPasswordHasher<ApplicationUser> passwordHasher, IEnumerable<IUserValidator<ApplicationUser>> userValidators,
        IEnumerable<IPasswordValidator<ApplicationUser>> passwordValidators, ILookupNormalizer keyNormalizer,
        IdentityErrorDescriber errors, IServiceProvider serviceProvider, ILogger<UserManager<ApplicationUser>> logger)
  : base(store, optionsAccessor, new SqlPasswordHasher(), userValidators, passwordValidators, keyNormalizer, errors,
        serviceProvider, logger)
{
}

在 SqlPasswordHasher 中,我只是重写了 verifyHashedPassword 方法,如下所示:

public override PasswordVerificationResult VerifyHashedPassword(ApplicationUser user, string hashedPassword, string providedPassword)
{
    // My custom logic is here
    ...
}

但是,上面的方法不起作用。我在 SqlPasswordHasher 的VerifyHashedPassword 方法中设置了一个断点,但它没有被触发。

我认为我的处理方式是错误的,我应该利用 DI 来实现这一点。我更新了用户管理器的构造函数,以便它不会实例化新的 SqlPasswordHasher,而是使用默认接口(interface)参数:

public ApplicationUserManager(IUserStore<ApplicationUser> store, IOptions<IdentityOptions> optionsAccessor,
        IPasswordHasher<ApplicationUser> passwordHasher, IEnumerable<IUserValidator<ApplicationUser>> userValidators,
        IEnumerable<IPasswordValidator<ApplicationUser>> passwordValidators, ILookupNormalizer keyNormalizer,
        IdentityErrorDescriber errors, IServiceProvider serviceProvider, ILogger<UserManager<ApplicationUser>> logger)
  : base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors,
        serviceProvider, logger)
{
}

然后在 Startup.cs 中我添加了一个范围服务:

services.AddScoped<IPasswordHasher<ApplicationUser>, SqlPasswordHasher>();

但同样,这不起作用,并且 SqlPasswordHasher 中的断点永远不会被触发。

我的自定义登录管理器有类似的行:

services.AddScoped<SignInManager<ApplicationUser>, ApplicationSignInManager>();

效果很好。 ApplicationSignInManager 采用 UserManager 参数,我可以看到 UserManager 采用 IPasswordHasher 参数。

我假设 SignInManager 使用 UserManager,而 UserManager 使用 PasswordHasher。所以我的问题是,如何让 UserManager 使用我的自定义密码哈希器?或者,如果情况并非如此,我如何让 SignInManager 使用我的密码哈希器?

编辑:我已经能够确认当我的 ApplicationUserManager 实例化时,我的 SqlPasswordHasher 正在构造函数中使用,因此 DI 可以正常工作。我只是不明白为什么我对VerifyHashedPassword 的覆盖没有被触发。

最佳答案

事实证明,问题与代码根本无关。通过将我的 SqlPasswordHasher 添加到服务

services.AddScoped<IPasswordHasher<ApplicationUser>, SqlPasswordHasher>();

工作完美。

问题在于我如何迁移数据。由于我使用的现有数据库与旧版本的 Identity 一起使用,因此我必须将以下字段添加到现有的 AspNetUsers 表中:

NormalizedUserName
ConcurrencyStamp
LockoutEnd
NormalizedEmail

但是我没有填充 NormalizedUserName 或 NormalizedEmail 字段。这就是为什么它永远不会触发我对VerifyHashedPassword的覆盖;因为它从未找到我的用户,因为它是根据 NormalizedUserName 进行查找的。

一旦我填充了这些字段,它就开始触发我的VerifyHashedPassword 方法。

关于asp.net-core - ASP.NET Core Identity - 扩展密码哈希器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37333399/

相关文章:

c# - 在 HttpWebRequest 中提交请求后无法执行此操作

asp.net-core - 能否更改 Visual Studio 2022 Dockerized ASP .NET Core 应用程序的默认浏览器?

asp.net-core - 将自定义数据存储在 Identity Cookie 中

asp.net - 如何在 PasswordSignInAsync 之前检查 AspNetUser 是否满足条件?

visual-studio-2015 - 安装 Dot Net Core 1.0.0 VS 2015 Tools Preview 2 时出现问题

c# - 在 ASP.NET Core Web Api 中发布流

c# - ViewComponents 不是异步的

c# - 使用 Table-Per-Hierarchy 继承模型访问相关实体的影子属性

c# - 无法将数据写入传输。 vs2017 ASP.net core 脚手架(MSSQL WINDOW 10)

asp.net-core - 带有 ASP.NET Identity 3 的 JWT 不记名 token