Browse Source

Add ShouldPeriodicallyChangePassword

pull/15955/head
liangshiwei 3 years ago
parent
commit
1ff9090e4c
  1. 14
      modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs
  2. 20
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs
  3. 11
      modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserStore.cs
  4. 16
      modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs
  5. 10
      modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs

14
modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs

@ -19,6 +19,8 @@ public class AbpSignInManager : SignInManager<IdentityUser>
protected IClock Clock { get; } protected IClock Clock { get; }
private readonly IdentityUserManager _identityUserManager;
public AbpSignInManager( public AbpSignInManager(
IdentityUserManager userManager, IdentityUserManager userManager,
IHttpContextAccessor contextAccessor, IHttpContextAccessor contextAccessor,
@ -41,6 +43,7 @@ public class AbpSignInManager : SignInManager<IdentityUser>
SettingProvider = settingProvider; SettingProvider = settingProvider;
Clock = clock; Clock = clock;
AbpOptions = options.Value; AbpOptions = options.Value;
_identityUserManager = userManager;
} }
public override async Task<SignInResult> PasswordSignInAsync( public override async Task<SignInResult> PasswordSignInAsync(
@ -101,16 +104,9 @@ public class AbpSignInManager : SignInManager<IdentityUser>
return SignInResult.NotAllowed; return SignInResult.NotAllowed;
} }
var forceUsersToPeriodicallyChangePassword = await SettingProvider.GetAsync<bool>(IdentitySettingNames.Password.ForceUsersToPeriodicallyChangePassword); if (await _identityUserManager.ShouldPeriodicallyChangePasswordAsync(user))
if (forceUsersToPeriodicallyChangePassword)
{ {
var passwordChangePeriodDays = await SettingProvider.GetAsync<int>(IdentitySettingNames.Password.PasswordChangePeriodDays); return SignInResult.NotAllowed;
var lastPasswordChangeTime = user.LastPasswordChangeTime ?? user.CreationTime;
if (passwordChangePeriodDays > 0 && lastPasswordChangeTime.AddDays(passwordChangePeriodDays) < Clock.Now)
{
Logger.LogWarning($"The user should change password! (username: \"{user.UserName}\", id:\"{user.Id}\")");
return SignInResult.NotAllowed;
}
} }
return await base.PreSignInCheck(user); return await base.PreSignInCheck(user);

20
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs

@ -259,14 +259,24 @@ public class IdentityUserManager : UserManager<IdentityUser>, IDomainService
return await UpdateUserAsync(user); return await UpdateUserAsync(user);
} }
protected async override Task<IdentityResult> UpdatePasswordHash(IdentityUser user, string newPassword, bool validatePassword) public virtual async Task<bool> ShouldPeriodicallyChangePasswordAsync(IdentityUser user)
{ {
var result = await base.UpdatePasswordHash(user, newPassword, validatePassword); Check.NotNull(user, nameof(user));
if (result.Succeeded && user.Id != default)
if (user.PasswordHash.IsNullOrWhiteSpace())
{
return false;
}
var forceUsersToPeriodicallyChangePassword = await SettingProvider.GetAsync<bool>(IdentitySettingNames.Password.ForceUsersToPeriodicallyChangePassword);
if (!forceUsersToPeriodicallyChangePassword)
{ {
user.SetLastPasswordChangeTime(Clock.Now); return false;
} }
return result; var lastPasswordChangeTime = user.LastPasswordChangeTime ?? user.CreationTime;
var passwordChangePeriodDays = await SettingProvider.GetAsync<int>(IdentitySettingNames.Password.PasswordChangePeriodDays);
return passwordChangePeriodDays > 0 && lastPasswordChangeTime.AddDays(passwordChangePeriodDays) < Clock.Now;
} }
} }

11
modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserStore.cs

@ -12,6 +12,7 @@ using Volo.Abp.Data;
using Volo.Abp.DependencyInjection; using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories; using Volo.Abp.Domain.Repositories;
using Volo.Abp.Guids; using Volo.Abp.Guids;
using Volo.Abp.Timing;
namespace Volo.Abp.Identity; namespace Volo.Abp.Identity;
@ -55,6 +56,7 @@ public class IdentityUserStore :
protected ILogger<IdentityRoleStore> Logger { get; } protected ILogger<IdentityRoleStore> Logger { get; }
protected ILookupNormalizer LookupNormalizer { get; } protected ILookupNormalizer LookupNormalizer { get; }
protected IIdentityUserRepository UserRepository { get; } protected IIdentityUserRepository UserRepository { get; }
protected IClock Clock { get; }
public IdentityUserStore( public IdentityUserStore(
IIdentityUserRepository userRepository, IIdentityUserRepository userRepository,
@ -62,6 +64,7 @@ public class IdentityUserStore :
IGuidGenerator guidGenerator, IGuidGenerator guidGenerator,
ILogger<IdentityRoleStore> logger, ILogger<IdentityRoleStore> logger,
ILookupNormalizer lookupNormalizer, ILookupNormalizer lookupNormalizer,
IClock clock,
IdentityErrorDescriber describer = null) IdentityErrorDescriber describer = null)
{ {
UserRepository = userRepository; UserRepository = userRepository;
@ -69,6 +72,7 @@ public class IdentityUserStore :
GuidGenerator = guidGenerator; GuidGenerator = guidGenerator;
Logger = logger; Logger = logger;
LookupNormalizer = lookupNormalizer; LookupNormalizer = lookupNormalizer;
Clock = clock;
ErrorDescriber = describer ?? new IdentityErrorDescriber(); ErrorDescriber = describer ?? new IdentityErrorDescriber();
} }
@ -260,7 +264,7 @@ public class IdentityUserStore :
/// <param name="passwordHash">The password hash to set.</param> /// <param name="passwordHash">The password hash to set.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns> /// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
public virtual Task SetPasswordHashAsync([NotNull] IdentityUser user, string passwordHash, CancellationToken cancellationToken = default) public virtual async Task SetPasswordHashAsync([NotNull] IdentityUser user, string passwordHash, CancellationToken cancellationToken = default)
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
@ -268,7 +272,10 @@ public class IdentityUserStore :
user.PasswordHash = passwordHash; user.PasswordHash = passwordHash;
return Task.CompletedTask; if (await FindByIdAsync(user.Id.ToString(), cancellationToken) != null)
{
user.SetLastPasswordChangeTime(Clock.Now);
}
} }
/// <summary> /// <summary>

16
modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs

@ -31,7 +31,7 @@ namespace Volo.Abp.IdentityServer.AspNetIdentity;
public class AbpResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator public class AbpResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
{ {
protected SignInManager<IdentityUser> SignInManager { get; } protected SignInManager<IdentityUser> SignInManager { get; }
protected UserManager<IdentityUser> UserManager { get; } protected IdentityUserManager UserManager { get; }
protected IdentitySecurityLogManager IdentitySecurityLogManager { get; } protected IdentitySecurityLogManager IdentitySecurityLogManager { get; }
protected ILogger<ResourceOwnerPasswordValidator<IdentityUser>> Logger { get; } protected ILogger<ResourceOwnerPasswordValidator<IdentityUser>> Logger { get; }
protected IStringLocalizer<AbpIdentityServerResource> Localizer { get; } protected IStringLocalizer<AbpIdentityServerResource> Localizer { get; }
@ -44,7 +44,7 @@ public class AbpResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
protected IClock Clock { get; } protected IClock Clock { get; }
public AbpResourceOwnerPasswordValidator( public AbpResourceOwnerPasswordValidator(
UserManager<IdentityUser> userManager, IdentityUserManager userManager,
SignInManager<IdentityUser> signInManager, SignInManager<IdentityUser> signInManager,
IdentitySecurityLogManager identitySecurityLogManager, IdentitySecurityLogManager identitySecurityLogManager,
ILogger<ResourceOwnerPasswordValidator<IdentityUser>> logger, ILogger<ResourceOwnerPasswordValidator<IdentityUser>> logger,
@ -140,16 +140,10 @@ public class AbpResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
return; return;
} }
var forceUsersToPeriodicallyChangePassword = await SettingProvider.GetAsync<bool>(IdentitySettingNames.Password.ForceUsersToPeriodicallyChangePassword); if (await UserManager.ShouldPeriodicallyChangePasswordAsync(user))
if (forceUsersToPeriodicallyChangePassword)
{ {
var passwordChangePeriodDays = await SettingProvider.GetAsync<int>(IdentitySettingNames.Password.PasswordChangePeriodDays); await HandlePeriodicallyChangePasswordAsync(context, user, context.Password);
var lastPasswordChangeTime = user.LastPasswordChangeTime ?? user.CreationTime; return;
if (passwordChangePeriodDays > 0 && lastPasswordChangeTime.AddDays(passwordChangePeriodDays) < Clock.Now)
{
await HandlePeriodicallyChangePasswordAsync(context, user, context.Password);
return;
}
} }
errorDescription = Localizer["LoginIsNotAllowed"]; errorDescription = Localizer["LoginIsNotAllowed"];

10
modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs

@ -111,15 +111,9 @@ public partial class TokenController
return await HandleShouldChangePasswordOnNextLoginAsync(request, user, request.Password); return await HandleShouldChangePasswordOnNextLoginAsync(request, user, request.Password);
} }
var forceUsersToPeriodicallyChangePassword = await SettingProvider.GetAsync<bool>(IdentitySettingNames.Password.ForceUsersToPeriodicallyChangePassword); if (await UserManager.ShouldPeriodicallyChangePasswordAsync(user))
if (forceUsersToPeriodicallyChangePassword)
{ {
var passwordChangePeriodDays = await SettingProvider.GetAsync<int>(IdentitySettingNames.Password.PasswordChangePeriodDays); return await HandlePeriodicallyChangePasswordAsync(request, user, request.Password);
var lastPasswordChangeTime = user.LastPasswordChangeTime ?? user.CreationTime;
if (passwordChangePeriodDays > 0 && lastPasswordChangeTime.AddDays(passwordChangePeriodDays) < Clock.Now)
{
return await HandlePeriodicallyChangePasswordAsync(request, user, request.Password);
}
} }
errorDescription = "You are not allowed to login! Your account is inactive or needs to confirm your email/phone number."; errorDescription = "You are not allowed to login! Your account is inactive or needs to confirm your email/phone number.";

Loading…
Cancel
Save