Asp.net

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

  • May 26, 2016

我正在嘗試根據使用者的角色將使用者重定向到頁面,

這是 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,這是預期的行為。

如果我此時使用雇主帳戶登錄,它會將我重定向到雇首頁面並以雇主身份登錄,這沒有錯,但情況不應該如此,該網站應該提到我應該登錄一個管理員帳戶,因為返回 url 是“管理員”。我希望我說得通。

為什麼不在自定義重定向之前檢查是否有 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). 因此需要防止開放重定向攻擊。

引用自:https://stackoverflow.com/questions/26526536