ASP.NET Core身份-扩展密码哈希器 [英] ASP.NET Core Identity - Extending Password Hasher

查看:255
本文介绍了ASP.NET Core身份-扩展密码哈希器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力将应用程序从Web窗体迁移到MVC,并选择使用ASP.NET Core与MVC 6一起使用.

I'm working towards moving an application from Web Forms to MVC and opted to go with MVC 6 using ASP.NET Core.

在我当前的应用程序中,我有一个用于Identity的自定义密码哈希器.在我的自定义UserManager类中,实现非常简单:

In my current application I have a custom password hasher used with Identity. The implementation is very simple in my custom UserManager class:

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

我正在尝试对.NET Core进行同样的操作,但是UserManager中不存在PasswordHasher属性.我看到构造函数将使用IPasswordHasher参数,因此我尝试了此操作:

I'm trying to do the same with .NET Core but the PasswordHasher property doesn't exist in UserManager. I see that the constructor will take an IPasswordHasher parameter so I tried this:

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方法,如下所示:

In SqlPasswordHasher I'm simply overriding the VerifyHashedPassword method which looks like this:

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

但是,以上操作无效.我在SqlPasswordHasher的VerifyHashedPassword方法中设置了一个断点,并且不会触发该断点.

However, the above doesn't work. I have a breakpoint set in the VerifyHashedPassword method of SqlPasswordHasher and it doesn't get triggered.

我以为我要走错路了,我应该利用DI来做到这一点.我更新了用户管理器的构造函数,以使其不实例化新的SqlPasswordHasher,但改用默认的接口参数:

I thought I was going about this the wrong way and I should be utilizing DI to accomplish this. I updated the constructor of my user manager so that it doesn't instantiate a new SqlPasswordHasher, but uses the default interface parameter instead:

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中,我添加了作用域服务:

Then in Startup.cs I added a scoped service:

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

但是再次,这是行不通的,并且永远不会触发SqlPasswordHasher中的断点.

But again, this doesn't work and the breakpoint in SqlPasswordHasher is never triggered.

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

I have a similar line for my custom Sign In Manager:

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

那很好. ApplicationSignInManager使用UserManager参数,我可以看到UserManager使用IPasswordHasher参数.

That works great. The ApplicationSignInManager takes a UserManager parameter and I can see that the UserManager takes an IPasswordHasher parameter.

我假设SignInManager使用的UserManager使用的是PasswordHasher.所以我的问题是,如何让UserManager使用我的自定义密码哈希器?或者,如果不是这种情况,我如何让SignInManager使用我的密码哈希器?

I'm assuming SignInManager uses the UserManager which uses the PasswordHasher. So my question is, how do I get the UserManager to use my custom Password Hasher? Or if thats not the case, how do I get the SignInManager to use my Password hasher?

我已经能够确认实例化我的ApplicationUserManager时,在构造函数中使用了我的SqlPasswordHasher,因此DI可以正常工作.我只是不知道为什么未触发我对VerifyHashedPassword的覆盖.

I've been able to confirm that when my ApplicationUserManager is instantiated, my SqlPasswordHasher is being used in the constructor so the DI is working properly. I just can't figure out why my override of VerifyHashedPassword is not being triggered.

推荐答案

事实证明问题根本与代码无关.通过

It turns out the problem was not related to code at all. Adding my SqlPasswordHasher to the services via

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

做得很好.

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

The problem was with how I migrated the data. Since I was using an existing database that was being used with an older version of Identity, I had to add the following fields to my existing AspNetUsers table:

NormalizedUserName
ConcurrencyStamp
LockoutEnd
NormalizedEmail

但是我没有填充NormalizedUserName或NormalizedEmail字段.这就是为什么它永远不会触发我对VerifyHashedPassword的覆盖;因为它是基于NormalizedUserName查找的,所以从未找到我的用户.

However I didn't populate the NormalizedUserName or NormalizedEmail fields. So that's why it was never triggering my override of VerifyHashedPassword; because it never found my user since it was looking up based on NormalizedUserName.

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

Once I populated those fields it started triggering my VerifyHashedPassword method.

这篇关于ASP.NET Core身份-扩展密码哈希器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆