Pass user to IPasswordHasher

This commit is contained in:
Hao Kung 2014-07-25 11:57:13 -07:00
parent 7f2ae65e3d
commit 7942d2bc82
11 changed files with 26 additions and 22 deletions

View File

@ -6,21 +6,23 @@ namespace Microsoft.AspNet.Identity
/// <summary> /// <summary>
/// Abstraction for password hashing methods /// Abstraction for password hashing methods
/// </summary> /// </summary>
public interface IPasswordHasher public interface IPasswordHasher<TUser> where TUser : class
{ {
/// <summary> /// <summary>
/// Hash a password /// Hash a password
/// </summary> /// </summary>
/// <param name="user"></param>
/// <param name="password"></param> /// <param name="password"></param>
/// <returns></returns> /// <returns></returns>
string HashPassword(string password); string HashPassword(TUser user, string password);
/// <summary> /// <summary>
/// Verify that a password matches the hashed password /// Verify that a password matches the hashed password
/// </summary> /// </summary>
/// <param name="user"></param>
/// <param name="hashedPassword"></param> /// <param name="hashedPassword"></param>
/// <param name="providedPassword"></param> /// <param name="providedPassword"></param>
/// <returns></returns> /// <returns></returns>
PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword); PasswordVerificationResult VerifyHashedPassword(TUser user, string hashedPassword, string providedPassword);
} }
} }

View File

@ -25,7 +25,7 @@ namespace Microsoft.AspNet.Identity
yield return describe.Transient<IUserValidator<TUser>, UserValidator<TUser>>(); yield return describe.Transient<IUserValidator<TUser>, UserValidator<TUser>>();
yield return describe.Transient<IPasswordValidator<TUser>, PasswordValidator<TUser>>(); yield return describe.Transient<IPasswordValidator<TUser>, PasswordValidator<TUser>>();
yield return describe.Transient<IPasswordHasher, PasswordHasher>(); yield return describe.Transient<IPasswordHasher<TUser>, PasswordHasher<TUser>>();
// TODO: rationalize email/sms/usertoken services // TODO: rationalize email/sms/usertoken services
} }

View File

@ -6,14 +6,15 @@ namespace Microsoft.AspNet.Identity
/// <summary> /// <summary>
/// Implements password hashing methods /// Implements password hashing methods
/// </summary> /// </summary>
public class PasswordHasher : IPasswordHasher public class PasswordHasher<TUser> : IPasswordHasher<TUser> where TUser : class
{ {
/// <summary> /// <summary>
/// Hash a password /// Hash a password
/// </summary> /// </summary>
/// <param name="user"></param>
/// <param name="password"></param> /// <param name="password"></param>
/// <returns></returns> /// <returns></returns>
public virtual string HashPassword(string password) public virtual string HashPassword(TUser user, string password)
{ {
return Crypto.HashPassword(password); return Crypto.HashPassword(password);
} }
@ -21,10 +22,11 @@ namespace Microsoft.AspNet.Identity
/// <summary> /// <summary>
/// Verify that a password matches the hashedPassword /// Verify that a password matches the hashedPassword
/// </summary> /// </summary>
/// <param name="user"></param>
/// <param name="hashedPassword"></param> /// <param name="hashedPassword"></param>
/// <param name="providedPassword"></param> /// <param name="providedPassword"></param>
/// <returns></returns> /// <returns></returns>
public virtual PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword) public virtual PasswordVerificationResult VerifyHashedPassword(TUser user, string hashedPassword, string providedPassword)
{ {
return Crypto.VerifyHashedPassword(hashedPassword, providedPassword) return Crypto.VerifyHashedPassword(hashedPassword, providedPassword)
? PasswordVerificationResult.Success ? PasswordVerificationResult.Success

View File

@ -24,7 +24,7 @@ namespace Microsoft.AspNet.Identity
private TimeSpan _defaultLockout = TimeSpan.Zero; private TimeSpan _defaultLockout = TimeSpan.Zero;
private bool _disposed; private bool _disposed;
private IPasswordHasher _passwordHasher; private IPasswordHasher<TUser> _passwordHasher;
private IdentityOptions _options; private IdentityOptions _options;
/// <summary> /// <summary>
@ -37,7 +37,7 @@ namespace Microsoft.AspNet.Identity
/// <param name="passwordValidator"></param> /// <param name="passwordValidator"></param>
/// <param name="claimsIdentityFactory"></param> /// <param name="claimsIdentityFactory"></param>
public UserManager(IUserStore<TUser> store, IOptionsAccessor<IdentityOptions> optionsAccessor, public UserManager(IUserStore<TUser> store, IOptionsAccessor<IdentityOptions> optionsAccessor,
IPasswordHasher passwordHasher, IUserValidator<TUser> userValidator, IPasswordHasher<TUser> passwordHasher, IUserValidator<TUser> userValidator,
IPasswordValidator<TUser> passwordValidator) IPasswordValidator<TUser> passwordValidator)
{ {
if (store == null) if (store == null)
@ -68,7 +68,7 @@ namespace Microsoft.AspNet.Identity
/// <summary> /// <summary>
/// Used to hash/verify passwords /// Used to hash/verify passwords
/// </summary> /// </summary>
public IPasswordHasher PasswordHasher public IPasswordHasher<TUser> PasswordHasher
{ {
get get
{ {
@ -618,7 +618,7 @@ namespace Microsoft.AspNet.Identity
} }
} }
await await
passwordStore.SetPasswordHashAsync(user, PasswordHasher.HashPassword(newPassword), cancellationToken); passwordStore.SetPasswordHashAsync(user, PasswordHasher.HashPassword(user, newPassword), cancellationToken);
await UpdateSecurityStampInternal(user, cancellationToken); await UpdateSecurityStampInternal(user, cancellationToken);
return IdentityResult.Success; return IdentityResult.Success;
} }
@ -635,7 +635,7 @@ namespace Microsoft.AspNet.Identity
string password, CancellationToken cancellationToken = default(CancellationToken)) string password, CancellationToken cancellationToken = default(CancellationToken))
{ {
var hash = await store.GetPasswordHashAsync(user, cancellationToken); var hash = await store.GetPasswordHashAsync(user, cancellationToken);
return PasswordHasher.VerifyHashedPassword(hash, password) != PasswordVerificationResult.Failed; return PasswordHasher.VerifyHashedPassword(user, hash, password) != PasswordVerificationResult.Failed;
} }
// IUserSecurityStampStore methods // IUserSecurityStampStore methods

View File

@ -309,7 +309,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test
var user = new IdentityUser("CanUpdatePasswordUsingHasher"); var user = new IdentityUser("CanUpdatePasswordUsingHasher");
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user, "password")); IdentityResultAssert.IsSuccess(await manager.CreateAsync(user, "password"));
Assert.True(await manager.CheckPasswordAsync(user, "password")); Assert.True(await manager.CheckPasswordAsync(user, "password"));
user.PasswordHash = manager.PasswordHasher.HashPassword("New"); user.PasswordHash = manager.PasswordHasher.HashPassword(user, "New");
IdentityResultAssert.IsSuccess(await manager.UpdateAsync(user)); IdentityResultAssert.IsSuccess(await manager.UpdateAsync(user));
Assert.False(await manager.CheckPasswordAsync(user, "password")); Assert.False(await manager.CheckPasswordAsync(user, "password"));
Assert.True(await manager.CheckPasswordAsync(user, "New")); Assert.True(await manager.CheckPasswordAsync(user, "New"));

View File

@ -190,7 +190,7 @@ namespace Microsoft.AspNet.Identity.EntityFramework.Test
var user = new ApplicationUser(); var user = new ApplicationUser();
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user, "password")); IdentityResultAssert.IsSuccess(await manager.CreateAsync(user, "password"));
Assert.True(await manager.CheckPasswordAsync(user, "password")); Assert.True(await manager.CheckPasswordAsync(user, "password"));
user.PasswordHash = manager.PasswordHasher.HashPassword("New"); user.PasswordHash = manager.PasswordHasher.HashPassword(user, "New");
IdentityResultAssert.IsSuccess(await manager.UpdateAsync(user)); IdentityResultAssert.IsSuccess(await manager.UpdateAsync(user));
Assert.False(await manager.CheckPasswordAsync(user, "password")); Assert.False(await manager.CheckPasswordAsync(user, "password"));
Assert.True(await manager.CheckPasswordAsync(user, "New")); Assert.True(await manager.CheckPasswordAsync(user, "New"));

View File

@ -31,7 +31,7 @@ namespace Microsoft.AspNet.Identity.Test
[Fact] [Fact]
public void CanSpecifyPasswordHasherInstance() public void CanSpecifyPasswordHasherInstance()
{ {
CanOverride<IPasswordHasher>(new PasswordHasher()); CanOverride<IPasswordHasher<IdentityUser>>(new PasswordHasher<IdentityUser>());
} }
[Fact] [Fact]
@ -47,7 +47,7 @@ namespace Microsoft.AspNet.Identity.Test
var pwdValidator = provider.GetService<IPasswordValidator<IdentityUser>>() as PasswordValidator<IdentityUser>; var pwdValidator = provider.GetService<IPasswordValidator<IdentityUser>>() as PasswordValidator<IdentityUser>;
Assert.NotNull(pwdValidator); Assert.NotNull(pwdValidator);
var hasher = provider.GetService<IPasswordHasher>() as PasswordHasher; var hasher = provider.GetService<IPasswordHasher<IdentityUser>>() as PasswordHasher<IdentityUser>;
Assert.NotNull(hasher); Assert.NotNull(hasher);
} }

View File

@ -22,7 +22,7 @@ namespace Microsoft.AspNet.Identity.Test
public IUserStore<TestUser> StorePublic { get { return Store; } } public IUserStore<TestUser> StorePublic { get { return Store; } }
public TestManager(IUserStore<TestUser> store, IOptionsAccessor<IdentityOptions> optionsAccessor, public TestManager(IUserStore<TestUser> store, IOptionsAccessor<IdentityOptions> optionsAccessor,
IPasswordHasher passwordHasher, IUserValidator<TestUser> userValidator, IPasswordHasher<TestUser> passwordHasher, IUserValidator<TestUser> userValidator,
IPasswordValidator<TestUser> passwordValidator) IPasswordValidator<TestUser> passwordValidator)
: base(store, optionsAccessor, passwordHasher, userValidator, passwordValidator) { } : base(store, optionsAccessor, passwordHasher, userValidator, passwordValidator) { }
} }
@ -423,7 +423,7 @@ namespace Microsoft.AspNet.Identity.Test
{ {
var store = new NotImplementedStore(); var store = new NotImplementedStore();
var optionsAccessor = new OptionsAccessor<IdentityOptions>(null); var optionsAccessor = new OptionsAccessor<IdentityOptions>(null);
var passwordHasher = new PasswordHasher(); var passwordHasher = new PasswordHasher<TestUser>();
var userValidator = new UserValidator<TestUser>(); var userValidator = new UserValidator<TestUser>();
var passwordValidator = new PasswordValidator<TestUser>(); var passwordValidator = new PasswordValidator<TestUser>();

View File

@ -9,7 +9,7 @@ namespace Microsoft.AspNet.Identity.Test
public class ApplicationUserManager : UserManager<ApplicationUser> public class ApplicationUserManager : UserManager<ApplicationUser>
{ {
public ApplicationUserManager(IUserStore<ApplicationUser> store, IOptionsAccessor<IdentityOptions> options, public ApplicationUserManager(IUserStore<ApplicationUser> store, IOptionsAccessor<IdentityOptions> options,
IPasswordHasher passwordHasher, IUserValidator<ApplicationUser> userValidator, IPasswordHasher<ApplicationUser> passwordHasher, IUserValidator<ApplicationUser> userValidator,
IPasswordValidator<ApplicationUser> passwordValidator) IPasswordValidator<ApplicationUser> passwordValidator)
: base(store, options, passwordHasher, userValidator, passwordValidator) { } : base(store, options, passwordHasher, userValidator, passwordValidator) { }
} }

View File

@ -33,7 +33,7 @@ namespace Microsoft.AspNet.Identity.Test
{ {
var store = new Mock<IUserStore<TUser>>(); var store = new Mock<IUserStore<TUser>>();
var options = new OptionsAccessor<IdentityOptions>(null); var options = new OptionsAccessor<IdentityOptions>(null);
return new Mock<UserManager<TUser>>(store.Object, options, new PasswordHasher(), new UserValidator<TUser>(), new PasswordValidator<TUser>()); return new Mock<UserManager<TUser>>(store.Object, options, new PasswordHasher<TUser>(), new UserValidator<TUser>(), new PasswordValidator<TUser>());
} }
public static Mock<RoleManager<TRole>> MockRoleManager<TRole>() where TRole : class public static Mock<RoleManager<TRole>> MockRoleManager<TRole>() where TRole : class
@ -51,7 +51,7 @@ namespace Microsoft.AspNet.Identity.Test
{ {
var options = new OptionsAccessor<IdentityOptions>(null); var options = new OptionsAccessor<IdentityOptions>(null);
var validator = new Mock<UserValidator<TUser>>(); var validator = new Mock<UserValidator<TUser>>();
var userManager = new UserManager<TUser>(store, options, new PasswordHasher(), validator.Object, new PasswordValidator<TUser>()); var userManager = new UserManager<TUser>(store, options, new PasswordHasher<TUser>(), validator.Object, new PasswordValidator<TUser>());
validator.Setup(v => v.ValidateAsync(userManager, It.IsAny<TUser>(), CancellationToken.None)).Returns(Task.FromResult(IdentityResult.Success)).Verifiable(); validator.Setup(v => v.ValidateAsync(userManager, It.IsAny<TUser>(), CancellationToken.None)).Returns(Task.FromResult(IdentityResult.Success)).Verifiable();
return userManager; return userManager;
} }

View File

@ -67,7 +67,7 @@ namespace Microsoft.AspNet.Identity.Test
var user = new TUser() { UserName = "UpdatePassword" }; var user = new TUser() { UserName = "UpdatePassword" };
IdentityResultAssert.IsSuccess(await manager.CreateAsync(user, "password")); IdentityResultAssert.IsSuccess(await manager.CreateAsync(user, "password"));
Assert.True(await manager.CheckPasswordAsync(user, "password")); Assert.True(await manager.CheckPasswordAsync(user, "password"));
user.PasswordHash = manager.PasswordHasher.HashPassword("New"); user.PasswordHash = manager.PasswordHasher.HashPassword(user, "New");
IdentityResultAssert.IsSuccess(await manager.UpdateAsync(user)); IdentityResultAssert.IsSuccess(await manager.UpdateAsync(user));
Assert.False(await manager.CheckPasswordAsync(user, "password")); Assert.False(await manager.CheckPasswordAsync(user, "password"));
Assert.True(await manager.CheckPasswordAsync(user, "New")); Assert.True(await manager.CheckPasswordAsync(user, "New"));