首页 文章

ASP.NET核心身份 - 扩展密码哈希

提问于
浏览
6

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

在我目前的应用程序中,我有一个与Identity一起使用的自定义密码 . 在我的自定义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使用PasswordHasher . 所以我的问题是,如何让UserManager使用我的自定义密码哈希?或者如果不是这样,我如何让SignInManager使用我的密码加密器?

编辑:我已经能够确认当我的ApplicationUserManager被实例化时,我的SqlPasswordHasher正在构造函数中使用,因此DI正常工作 . 我无法弄清楚为什么我的覆盖VerifyHashedPassword没有被触发 .

1 回答

  • 12

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

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

    工作得很好 .

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

    NormalizedUserName
    ConcurrencyStamp
    LockoutEnd
    NormalizedEmail
    

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

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

相关问题