在 ASP.NET Core 中首次登录时强制重定向到另一个页面
Force Redirect to Another Page when First Time Login in ASP.NET Core
目前我正在为本地构建网络应用程序。当我创建新用户时,我会使用默认密码设置用户。我想,如果用户使用默认密码登录,它将重定向到更改密码页面。在更改密码之前,用户将无法访问任何页面。
我目前的解决方法是检查每个控制器,有什么智能方法可以做到这一点吗?
这是登录后的一些代码
[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);
}
对于另一个控制器,我们总是检查会话中的密码。如果密码与默认密码相同,我们将其重定向到 NewPassword
页面
提前致谢!
您可以使用 session
存储用户密码,如下所示
HttpContext.Session.SetString("Password", vm.password);
然后创建一个过滤器来检查用户是否使用默认密码登录
public class PasswordFilter: IAuthorizationFilter
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly ISession _session;
public PasswordFilter(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
_session = _httpContextAccessor.HttpContext.Session;
}
public void OnAuthorization(AuthorizationFilterContext context)
{
if (_session.GetString("Password") == Password.DefaultPassword)
{
context.Result = new RedirectResult(nameof(UserController.NewPassword));
}
}
}
最后,您可以通过将此属性添加到您的控制器来使用此过滤器
[TypeFilter(typeof(PasswordFilter))]
希望这种方法能达到你的目的。
正如@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);
}
}
现在我可以在我的另一个控制器中取消检查,我的登录将如下所示:
[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);
}
希望这对想要实现相同目标的任何人有所帮助。
谢谢!
目前我正在为本地构建网络应用程序。当我创建新用户时,我会使用默认密码设置用户。我想,如果用户使用默认密码登录,它将重定向到更改密码页面。在更改密码之前,用户将无法访问任何页面。
我目前的解决方法是检查每个控制器,有什么智能方法可以做到这一点吗?
这是登录后的一些代码
[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);
}
对于另一个控制器,我们总是检查会话中的密码。如果密码与默认密码相同,我们将其重定向到 NewPassword
页面
提前致谢!
您可以使用 session
存储用户密码,如下所示
HttpContext.Session.SetString("Password", vm.password);
然后创建一个过滤器来检查用户是否使用默认密码登录
public class PasswordFilter: IAuthorizationFilter
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly ISession _session;
public PasswordFilter(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
_session = _httpContextAccessor.HttpContext.Session;
}
public void OnAuthorization(AuthorizationFilterContext context)
{
if (_session.GetString("Password") == Password.DefaultPassword)
{
context.Result = new RedirectResult(nameof(UserController.NewPassword));
}
}
}
最后,您可以通过将此属性添加到您的控制器来使用此过滤器
[TypeFilter(typeof(PasswordFilter))]
希望这种方法能达到你的目的。
正如@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);
}
}
现在我可以在我的另一个控制器中取消检查,我的登录将如下所示:
[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);
}
希望这对想要实现相同目标的任何人有所帮助。
谢谢!