我正在尝试根据用户的角色将用户重定向到页面,
这是 ASP.NET MVC 5 附带的登录功能的默认实现:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
var user = await UserManager.FindAsync(model.UserName, model.Password);
if (user != null)
{
await SignInAsync(user, model.RememberMe);
return RedirectToLocal(returnUrl);
}
else
{
ModelState.AddModelError("", "Invalid username or password.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
private ActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Employer");
}
}
我希望能够根据用户的角色重定向用户,我尝试这样做:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
var user = await UserManager.FindAsync(model.UserName, model.Password);
if (user != null)
{
await SignInAsync(user, model.RememberMe);
//role Employer go to Employer page
if (UserManager.IsInRole(user.Id, "Employer"))
{
return RedirectToAction("Index", "Employer");
}
//role Admin go to Admin page
else if (UserManager.IsInRole(user.Id, "Admin"))
{
return RedirectToAction("Index", "Admin");
}
else
{
//no role
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "Invalid username or password.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
但是有一个问题,虽然该网站将我重定向到正确的页面,但如果我在未使用管理员帐户登录时通过输入 url foo.com/admin 进行导航,该网站会将我带到登录页面的 url 为 foo.com/Account/Login?ReturnUrl=%2Fadmin,这是预期的行为。
如果我此时使用雇主帐户登录,它会将我重定向到雇主页面并以雇主身份登录,这并没有错,但情况不应该如此,该网站应该提到我应该使用管理员帐户登录,因为返回网址是“admin”。我希望我说得有道理。
最佳答案
为什么不在自定义重定向之前检查是否有 returnUrl?
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (ModelState.IsValid)
{
var user = await UserManager.FindAsync(model.UserName, model.Password);
if (user != null)
{
await SignInAsync(user, model.RememberMe);
if (String.IsNullOrEmpty(returnUrl))
{
if (UserManager.IsInRole(user.Id, "Employer"))
{
return RedirectToAction("Index", "Employer");
}
//role Admin go to Admin page
if (UserManager.IsInRole(user.Id, "Admin"))
{
return RedirectToAction("Index", "Admin");
}
}
else
{
return RedirectToLocal(returnUrl);
}
}
else
{
ModelState.AddModelError("", "Invalid username or password.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
就像这样,如果您导航到 foo.com/admin,它将抛出 401 并重定向您登录。然后,如果您以雇主身份登录,则会抛出 401 错误并将您重定向回再次登录。
来自评论:“我可以只执行 Redirect(returnUrl) 并删除 RedirectToLocal 操作方法吗?”
RedirectToLocal(returnUrl)
方法检查是否 Url.IsLocalUrl(returnUrl)
。因此需要防止开放重定向攻击。
关于ASP.NET MVC 5 Identity 2 基于用户角色的登录重定向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26526536/