我需要"超级用户"能够更改身份系统中任何用户的密码。我检查了两个解决方案。
1)将这个重载函数添加到CustomUserManager for CRUD:
public async Task<IdentityResult> ChangePasswordAsync(TenantUser user, string newPassword)
{...}
使用具有令牌参数的原始函数,但控制器中的此功能不起作用并返回无效令牌:
string Token = await manager.GeneratePasswordResetTokenAsync(TenantUser);
var resultPasswordChange = await manager.ResetPasswordAsync(TenantUser, Token, model.TenantUsersPassword.Password);
自定义用户管理器:所有PRIVATE功能和参数已从orig UserManager复制到派生的CustomUserManager。 NotSupportedException的资源仍然无法使用...我对结果不满意...... 你能帮助我吗?什么是更好的?实现CustomUserManager或解决无效令牌错误?请问该怎么做?
示例您需要复制多一个函数(ChangePasswordAsync):
namespace Program.Models
{
public class TenantUserManager<TenantUser> : UserManager<TenantUser>, IDisposable where TenantUser : class
{
// protected const string ResetPasswordTokenPurpose = "ResetPassword";
// protected const string ConfirmEmailTokenPurpose = "EmailConfirmation";
private TimeSpan _defaultLockout = TimeSpan.Zero;
private bool _disposed;
private readonly HttpContext _context;
private CancellationToken CancellationToken => _context?.RequestAborted ?? CancellationToken.None;
/// <summary>
/// Constructs a new instance of <see cref="UserManager{TenantUser}"/>.
/// </summary>
/// <param name="store">The persistence store the manager will operate over.</param>
/// <param name="optionsAccessor">The accessor used to access the <see cref="IdentityOptions"/>.</param>
/// <param name="userValidators">A collection of <see cref="IUserValidator{TenantUser}"/> to validate users against.</param>
/// <param name="passwordValidators">A collection of <see cref="IPasswordValidator{TenantUser}"/> to validate passwords against.</param>
/// <param name="keyNormalizer">The <see cref="ILookupNormalizer"/> to use when generating index keys for users.</param>
/// <param name="errors">The <see cref="IdentityErrorDescriber"/> used to provider error messages.</param>
/// <param name="services">The <see cref="IServiceProvider"/> used to resolve services.</param>
public TenantUserManager(IUserStore<TenantUser> store, IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<TenantUser> passwordHasher, IEnumerable<IUserValidator<TenantUser>> userValidators,
IEnumerable<IPasswordValidator<TenantUser>> passwordValidators, ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors, IServiceProvider services, ILogger<UserManager<TenantUser>> logger, IHttpContextAccessor contextAccessor)
: base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger, contextAccessor)
{
}
/// <summary>
/// Gets or sets the persistence store the manager operates over.
/// </summary>
/// <value>The persistence store the manager operates over.</value>
protected internal IUserStore<TenantUser> Store { get; set; }
/// <summary>
/// Gets the <see cref="ILogger"/> used to log messages from the manager.
/// </summary>
/// <value>
/// The <see cref="ILogger"/> used to log messages from the manager.
/// </value>
// protected internal virtual ILogger Logger { get; set; }
internal IPasswordHasher<TenantUser> PasswordHasher { get; set; }
internal IList<IUserValidator<TenantUser>> UserValidators { get; } = new List<IUserValidator<TenantUser>>();
internal IList<IPasswordValidator<TenantUser>> PasswordValidators { get; } = new List<IPasswordValidator<TenantUser>>();
internal ILookupNormalizer KeyNormalizer { get; set; }
internal IdentityErrorDescriber ErrorDescriber { get; set; }
internal IdentityOptions Options { get; set; }
public async Task<IdentityResult> ChangePasswordAsync(TenantUser user, string newPassword)
{
ThrowIfDisposed();
var passwordStore = GetPasswordStore();
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
var result = await UpdatePasswordHash(passwordStore, user, newPassword);
if (!result.Succeeded)
{
return result;
}
return await UpdateUserAsync(user);
// Logger.LogWarning(2, "Change password failed for user {userId}.", await GeTenantUserIdAsync(user));
// return IdentityResult.Failed(ErrorDescriber.PasswordMismatch());
}
private static string NewSecurityStamp()
{
return Guid.NewGuid().ToString();
}
private IUserSecurityStampStore<TenantUser> GetSecurityStore()
{
var cast = Store as IUserSecurityStampStore<TenantUser>;
if (cast == null)
{
throw new NotSupportedException("Resources.StoreNotIUserSecurityStampStore");
}
return cast;
}
// Update the security stamp if the store supports it
internal async Task UpdateSecurityStampInternal(TenantUser user)
{
if (SupportsUserSecurityStamp)
{
await GetSecurityStore().SetSecurityStampAsync(user, NewSecurityStamp(), CancellationToken);
}
}
internal async Task<IdentityResult> UpdatePasswordHash(IUserPasswordStore<TenantUser> passwordStore,
TenantUser user, string newPassword, bool validatePassword = true)
{
if (validatePassword)
{
var validate = await ValidatePasswordInternal(user, newPassword);
if (!validate.Succeeded)
{
return validate;
}
}
var hash = newPassword != null ? PasswordHasher.HashPassword(user, newPassword) : null;
await passwordStore.SetPasswordHashAsync(user, hash, CancellationToken);
await UpdateSecurityStampInternal(user);
return IdentityResult.Success;
}
private async Task<IdentityResult> ValidateUserInternal(TenantUser user)
{
var errors = new List<IdentityError>();
foreach (var v in UserValidators)
{
var result = await v.ValidateAsync(this, user);
if (!result.Succeeded)
{
errors.AddRange(result.Errors);
}
}
if (errors.Count > 0)
{
// Logger.LogWarning(13, "User {userId} validation failed: {errors}.", await GeTenantUserIdAsync(user), string.Join(";", errors.Select(e => e.Code)));
return IdentityResult.Failed(errors.ToArray());
}
return IdentityResult.Success;
}
private async Task<IdentityResult> ValidatePasswordInternal(TenantUser user, string password)
{
var errors = new List<IdentityError>();
foreach (var v in PasswordValidators)
{
var result = await v.ValidateAsync(this, user, password);
if (!result.Succeeded)
{
errors.AddRange(result.Errors);
}
}
if (errors.Count > 0)
{
// Logger.LogWarning(14, "User {userId} password validation failed: {errors}.", await GeTenantUserIdAsync(user), string.Join(";", errors.Select(e => e.Code)));
return IdentityResult.Failed(errors.ToArray());
}
return IdentityResult.Success;
}
private async Task<IdentityResult> UpdateUserAsync(TenantUser user)
{
var result = await ValidateUserInternal(user);
if (!result.Succeeded)
{
return result;
}
await UpdateNormalizedUserNameAsync(user);
await UpdateNormalizedEmailAsync(user);
return await Store.UpdateAsync(user, CancellationToken);
}
private IUserPasswordStore<TenantUser> GetPasswordStore()
{
var cast = Store as IUserPasswordStore<TenantUser>;
if (cast == null)
{
throw new NotSupportedException("Resources.StoreNotIUserPasswordStore"); //Resources are not awailable
}
return cast;
}
/// <summary>
/// Releases the unmanaged resources used by the role manager and optionally releases the managed resources.
/// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
protected override void Dispose(bool disposing)
{
if (disposing && !_disposed)
{
Store.Dispose();
_disposed = true;
}
}
protected void ThrowIfDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(GetType().Name);
}
}
}