我正在配置我的应用程序来处理以下场景:当我创建一个新用户作为管理员时,会为该用户生成一个临时(随机)密码。用户首次登录后,需要修改密码。使用
MustChangePassword
类中的 AppUser : Identity
字段跟踪此要求。
我想强制用户在登录后必须立即更改密码。如果用户尝试访问任何其他链接,他们应该被重定向到“更改密码”页面。我认为配置中间件是最好的方法。
但是,根据我当前的配置(见下文),即使我提交更改密码表单,它仍然重定向到
/Account/ChangePassword.
public class CheckPasswordChangeMiddleware
{
private readonly RequestDelegate _next;
public CheckPasswordChangeMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context, UserManager<AppUser> userManager, SignInManager<AppUser> signInManager)
{
if (context.User.Identity.IsAuthenticated)
{
var user = await userManager.GetUserAsync(context.User);
if (user != null && user.MustChangePassword && !context.Request.Path.StartsWithSegments("/Account/ChangePassword"))
{
context.Response.Redirect("/Account/ChangePassword");
return;
}
}
await _next(context);
}
}
[Authorize]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ChangePassword(ChangePassword model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var result = await _accountService.ChangePasswordAsync(model);
if (result)
{
return RedirectToAction("Index", "Home");
}
ModelState.AddModelError(string.Empty, "An error occurred while changing the password.");
return View(model);
}
public async Task<bool> ChangePasswordAsync(ChangePassword model)
{
var user = await _userManager.GetUserAsync(_httpContextAccessor.HttpContext!.User);
if (user == null)
{
return false;
}
var changePasswordResult = await _userManager.ChangePasswordAsync(user, model.CurrentPassword, model.NewPassword);
if (changePasswordResult.Succeeded)
{
user.MustChangePassword = false;
await _userManager.UpdateAsync(user);
await _signInManager.RefreshSignInAsync(user);
return true;
}
return false;
}
感谢您的帮助或建议!
最好的方法是不要在
MustChangePassword
中添加 AppUser
字段,因为没有必要。您只会使用它一次,并且它将保留在那里未使用。
相反,请使用类型
claim
针对该用户添加 new Claim("MUST_CHANGE_PASSWORD","")
。
在您的中间件中:
public async Task InvokeAsync (HttpContext context)
{
if (context.User.Identity.IsAuthenticated)
{
if (context.User.HasClaim("MUST_CHANGE_PASSWORD","") && context.Request.Path != "/Account/ChangePassword")
{
context.Response.Redirect("/Account/ChangePassword");
return;
}
}
await _next(context);
}
在您的
ChangePassword
HttpPost
方法中,一旦更改密码,请删除该声明 userManager.RemoveClaimAsync(User, new Claim("MUST_CHANGE_PASSWORD",""))
。