[英]Asp.net Identity 2.0 - redirect externally authenticated user based on role at login
[英]ASP.NET MVC 5 Identity 2 Login redirect based on user role
我正在嘗試根據用戶的角色將用戶重定向到頁面,
這是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並重定向您再次登錄。
來自評論: “我可以只進行重定向(returnUrl)並刪除RedirectToLocal操作方法嗎?”
RedirectToLocal(returnUrl)
方法檢查Url.IsLocalUrl(returnUrl)
。 因此需要防止打開重定向攻擊。
盡管[ 這篇 ]文章寫於2008年,但它幫助我解決了這個問題。 它提供了在登錄時重定向用戶所需的所有代碼示例,而不會弄亂您的Login方法。 如果您添加新角色並希望重定向具有該角色的用戶,則只需在web.config中添加一行即可。
我確實遇到過一個問題。 在他的文章中,他有以下代碼,您可以將其放入AccountController(或者您想要執行重定向的任何位置):
/// <summary>
/// Redirect the user to a specific URL, as specified in the web.config, depending on their role.
/// If a user belongs to multiple roles, the first matching role in the web.config is used.
/// Prioritize the role list by listing higher-level roles at the top.
/// </summary>
/// <param name="username">Username to check the roles for</param>
private void RedirectLogin(string username)
{
LoginRedirectByRoleSection roleRedirectSection = (LoginRedirectByRoleSection)ConfigurationManager.GetSection("loginRedirectByRole");
foreach (RoleRedirect roleRedirect in roleRedirectSection.RoleRedirects)
{
if (Roles.IsUserInRole(username, roleRedirect.Role))
{
Response.Redirect(roleRedirect.Url);
}
}
}
我的應用程序未能找到角色提供程序,當我在web.config中添加一個時,我很難找到我的角色。 我決定拋棄角色提供程序並使用UserManager來獲取用戶和角色:
/// <summary>
/// Redirect the user to a specific URL, as specified in the web.config, depending on their role.
/// If a user belongs to multiple roles, the first matching role in the web.config is used.
/// Prioritize the role list by listing higher-level roles at the top.
/// </summary>
/// <param name="username">Username to check the roles for</param>
private void RedirectLogin(string username)
{
LoginRedirectByRoleSection roleRedirectSection = (LoginRedirectByRoleSection)ConfigurationManager.GetSection("loginRedirectByRole");
var user = UserManager.FindByName(username);
var rolesForUser = UserManager.GetRoles(user.Id);
foreach (RoleRedirect roleRedirect in roleRedirectSection.RoleRedirects)
{
if (rolesForUser.Contains(roleRedirect.Role))
{
Response.Redirect(roleRedirect.Url);
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.