首次登录 ASP.NET Core 时强制重定向到另一个页面

Jam*_*mes 9 c# asp.net-core asp.net-core-3.1

目前我正在为本地构建网络应用程序。当我创建新用户时,我使用默认密码设置用户。我想,如果用户使用默认密码登录,它将重定向到更改密码页面。用户在更改密码之前将无法访问任何页面。

我当前的解决方法是检查每个控制器,有什么智能方法可以做到这一点吗?

这是登录后的一些代码

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login([FromForm] LoginViewModel vm, string returnUrl = null)
{
    if (ModelState.IsValid)
    {
        var result = await repository.Login(vm);
        if (result.IsSuccess)
        {
            await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, result.Data,
                new AuthenticationProperties
                {
                    IssuedUtc = DateTime.UtcNow,
                    ExpiresUtc = DateTime.UtcNow.AddDays(1),
                    IsPersistent = false
                });

            if (vm.Password != Password.DefaultPassword)
            {
                return RedirectToLocal(returnUrl);
            }
            else
            {
                return RedirectToAction(nameof(UserController.NewPassword));
            }
        }
        else
        {
            ViewBag.ErrorMessage = result.ErrorMessage;
        }
    }

    return View(vm);
}
Run Code Online (Sandbox Code Playgroud)

对于其他控制器,我们总是检查会话中的密码。如果密码与默认密码相同,我们将其重定向到NewPassword页面

提前致谢!

Jam*_*mes 2

正如 @JHBonarius 所说,我当前的解决方法是使用自定义中间件重定向到新密码页面。

我的中间件如下所示:

public class CheckPasswordMiddleware
{
    private readonly RequestDelegate next;

    public CheckPasswordMiddleware(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        if (context.Request.Path != "/User/NewPassword" && context.User.Identity.IsAuthenticated)
        {
            var userId = context.User.Identity.GetUserId();
            if (!string.IsNullOrEmpty(userId))
            {
                var dbContext = context.RequestServices.GetRequiredService<DatabaseContext>();
                var passwordHash = await dbContext.User.Where(x => x.Id.ToLower() == userId.ToLower()).Select(x => x.Password).FirstOrDefaultAsync();
                if (Hash.Verify(Password.DefaultPassword, passwordHash))
                {
                    context.Response.Redirect("/User/NewPassword");
                }
            }
        }

        await next(context);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我可以摆脱其他控制器中的检查,我的登录将如下所示:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login([FromForm] LoginViewModel vm, string returnUrl = null)
{
    if (ModelState.IsValid)
    {
        var result = await repository.Login(vm);
        if (result.IsSuccess)
        {
            await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, result.Data,
                new AuthenticationProperties
                {
                    IssuedUtc = DateTime.UtcNow,
                    ExpiresUtc = DateTime.UtcNow.AddDays(1),
                    IsPersistent = false
                });
            return RedirectToLocal(returnUrl);
        }
        else
        {
            ViewBag.ErrorMessage = result.ErrorMessage;
        }
    }

    return View(vm);
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助任何想要实现相同目标的人。

谢谢!