From 1ff9090e4c3799f1894fd1a3ff2941ad0fd36bec Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Mon, 13 Mar 2023 17:51:08 +0800 Subject: [PATCH] Add ShouldPeriodicallyChangePassword --- .../Identity/AspNetCore/AbpSignInManager.cs | 14 +++++-------- .../Volo/Abp/Identity/IdentityUserManager.cs | 20 ++++++++++++++----- .../Volo/Abp/Identity/IdentityUserStore.cs | 11 ++++++++-- .../AbpResourceOwnerPasswordValidator.cs | 16 +++++---------- .../Controllers/TokenController.Password.cs | 10 ++-------- 5 files changed, 36 insertions(+), 35 deletions(-) diff --git a/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs b/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs index be6b74d98f..00d46b0c04 100644 --- a/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpSignInManager.cs @@ -19,6 +19,8 @@ public class AbpSignInManager : SignInManager protected IClock Clock { get; } + private readonly IdentityUserManager _identityUserManager; + public AbpSignInManager( IdentityUserManager userManager, IHttpContextAccessor contextAccessor, @@ -41,6 +43,7 @@ public class AbpSignInManager : SignInManager SettingProvider = settingProvider; Clock = clock; AbpOptions = options.Value; + _identityUserManager = userManager; } public override async Task PasswordSignInAsync( @@ -101,16 +104,9 @@ public class AbpSignInManager : SignInManager return SignInResult.NotAllowed; } - var forceUsersToPeriodicallyChangePassword = await SettingProvider.GetAsync(IdentitySettingNames.Password.ForceUsersToPeriodicallyChangePassword); - if (forceUsersToPeriodicallyChangePassword) + if (await _identityUserManager.ShouldPeriodicallyChangePasswordAsync(user)) { - var passwordChangePeriodDays = await SettingProvider.GetAsync(IdentitySettingNames.Password.PasswordChangePeriodDays); - 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 SignInResult.NotAllowed; } return await base.PreSignInCheck(user); diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs index eb3e591f79..785239c661 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs +++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserManager.cs @@ -259,14 +259,24 @@ public class IdentityUserManager : UserManager, IDomainService return await UpdateUserAsync(user); } - protected async override Task UpdatePasswordHash(IdentityUser user, string newPassword, bool validatePassword) + public virtual async Task ShouldPeriodicallyChangePasswordAsync(IdentityUser user) { - var result = await base.UpdatePasswordHash(user, newPassword, validatePassword); - if (result.Succeeded && user.Id != default) + Check.NotNull(user, nameof(user)); + + if (user.PasswordHash.IsNullOrWhiteSpace()) + { + return false; + } + + var forceUsersToPeriodicallyChangePassword = await SettingProvider.GetAsync(IdentitySettingNames.Password.ForceUsersToPeriodicallyChangePassword); + if (!forceUsersToPeriodicallyChangePassword) { - user.SetLastPasswordChangeTime(Clock.Now); + return false; } - return result; + var lastPasswordChangeTime = user.LastPasswordChangeTime ?? user.CreationTime; + var passwordChangePeriodDays = await SettingProvider.GetAsync(IdentitySettingNames.Password.PasswordChangePeriodDays); + + return passwordChangePeriodDays > 0 && lastPasswordChangeTime.AddDays(passwordChangePeriodDays) < Clock.Now; } } diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserStore.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserStore.cs index c8c8fd45a9..6385cd4297 100644 --- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserStore.cs +++ b/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.Domain.Repositories; using Volo.Abp.Guids; +using Volo.Abp.Timing; namespace Volo.Abp.Identity; @@ -55,6 +56,7 @@ public class IdentityUserStore : protected ILogger Logger { get; } protected ILookupNormalizer LookupNormalizer { get; } protected IIdentityUserRepository UserRepository { get; } + protected IClock Clock { get; } public IdentityUserStore( IIdentityUserRepository userRepository, @@ -62,6 +64,7 @@ public class IdentityUserStore : IGuidGenerator guidGenerator, ILogger logger, ILookupNormalizer lookupNormalizer, + IClock clock, IdentityErrorDescriber describer = null) { UserRepository = userRepository; @@ -69,6 +72,7 @@ public class IdentityUserStore : GuidGenerator = guidGenerator; Logger = logger; LookupNormalizer = lookupNormalizer; + Clock = clock; ErrorDescriber = describer ?? new IdentityErrorDescriber(); } @@ -260,7 +264,7 @@ public class IdentityUserStore : /// The password hash to set. /// The used to propagate notifications that the operation should be canceled. /// The that represents the asynchronous operation. - 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(); @@ -268,7 +272,10 @@ public class IdentityUserStore : user.PasswordHash = passwordHash; - return Task.CompletedTask; + if (await FindByIdAsync(user.Id.ToString(), cancellationToken) != null) + { + user.SetLastPasswordChangeTime(Clock.Now); + } } /// diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs index f2129fa0c8..92484d72ec 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AspNetIdentity/AbpResourceOwnerPasswordValidator.cs +++ b/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 { protected SignInManager SignInManager { get; } - protected UserManager UserManager { get; } + protected IdentityUserManager UserManager { get; } protected IdentitySecurityLogManager IdentitySecurityLogManager { get; } protected ILogger> Logger { get; } protected IStringLocalizer Localizer { get; } @@ -44,7 +44,7 @@ public class AbpResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator protected IClock Clock { get; } public AbpResourceOwnerPasswordValidator( - UserManager userManager, + IdentityUserManager userManager, SignInManager signInManager, IdentitySecurityLogManager identitySecurityLogManager, ILogger> logger, @@ -140,16 +140,10 @@ public class AbpResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator return; } - var forceUsersToPeriodicallyChangePassword = await SettingProvider.GetAsync(IdentitySettingNames.Password.ForceUsersToPeriodicallyChangePassword); - if (forceUsersToPeriodicallyChangePassword) + if (await UserManager.ShouldPeriodicallyChangePasswordAsync(user)) { - var passwordChangePeriodDays = await SettingProvider.GetAsync(IdentitySettingNames.Password.PasswordChangePeriodDays); - var lastPasswordChangeTime = user.LastPasswordChangeTime ?? user.CreationTime; - if (passwordChangePeriodDays > 0 && lastPasswordChangeTime.AddDays(passwordChangePeriodDays) < Clock.Now) - { - await HandlePeriodicallyChangePasswordAsync(context, user, context.Password); - return; - } + await HandlePeriodicallyChangePasswordAsync(context, user, context.Password); + return; } errorDescription = Localizer["LoginIsNotAllowed"]; diff --git a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs b/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs index 5ba8aa9090..dd9d46b2de 100644 --- a/modules/openiddict/src/Volo.Abp.OpenIddict.AspNetCore/Volo/Abp/OpenIddict/Controllers/TokenController.Password.cs +++ b/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); } - var forceUsersToPeriodicallyChangePassword = await SettingProvider.GetAsync(IdentitySettingNames.Password.ForceUsersToPeriodicallyChangePassword); - if (forceUsersToPeriodicallyChangePassword) + if (await UserManager.ShouldPeriodicallyChangePasswordAsync(user)) { - var passwordChangePeriodDays = await SettingProvider.GetAsync(IdentitySettingNames.Password.PasswordChangePeriodDays); - var lastPasswordChangeTime = user.LastPasswordChangeTime ?? user.CreationTime; - if (passwordChangePeriodDays > 0 && lastPasswordChangeTime.AddDays(passwordChangePeriodDays) < Clock.Now) - { - return await HandlePeriodicallyChangePasswordAsync(request, user, request.Password); - } + 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.";