簡體   English   中英

ASP.NET MVC 5 Identity 2基於用戶角色的登錄重定向

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM