2014-10-23 2 views
10

Я пытаюсь перенаправить пользователя на страницу в зависимости от их роли,ASP.NET MVC 5 Идентичность 2 Войти редирект на основе роли пользователя

Это реализацию по умолчанию функции входа, которые приходят с 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); 
} 

но есть проблема, хотя сайт перенаправляет меня к й e correct page, Если я нахожусь, набрав url foo.com/admin, когда я не вошел в систему с учетной записью администратора, сайт приводит меня на страницу входа с URL-адресом foo.com/Account/Login?ReturnUrl=%2Fadmin , что является ожидаемым поведением.

Если я вхожу в систему с учетной записью работодателя на этом этапе, он перенаправит меня на страницу работодателя и зарегистрирует меня как работодателя, что не так, но это не должно быть так, сайт должен упоминать Я должен войти в систему с учетной записью администратора, потому что возвращаемый URL-адрес - «admin». Надеюсь, у меня есть смысл.

ответ

16

Почему вы не проверяете, есть ли returnUrl перед вашими пользовательскими перенаправлением?

Нравится это, если вы перейдете на сайт foo.com/admin, он бросит 401 и перенаправит вас на вход. Затем, если вы войдете в систему как работодатель, он бросит 401 и перенаправит вас снова на логин.

Из комментариев: «Могу ли я просто перенаправить (returnUrl) и удалить метод действия RedirectToLocal?»

RedirectToLocal(returnUrl) способ проверки, если Url.IsLocalUrl(returnUrl). Таким образом, это необходимо для предотвращения Open Redirect Attacks.

+0

Привет, Не могли бы вы объяснить, почему инструкция else возвращает RedirectToLocal (returnUrl); необходим? – Mindless

+0

Могу ли я просто перенаправить (returnUrl) и удалить метод действия RedirectToLocal? – Mindless

+0

вам нужна причина проверки (Url.IsLocalUrl (returnUrl)) – tmg

1

Несмотря на [this] статью, написанную в 2008 году, она помогла мне в решении этой проблемы. Он дает все образцы кода, необходимые для перенаправления пользователей при входе в систему без загромождения вашего метода входа. Если вы добавите новую роль и хотите перенаправить пользователей с этой ролью, это так же просто, как добавить строку в 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); 
     } 
    } 
} 

Моя заявка была не в состоянии найти поставщика роли, и когда я добавил один в Интернете .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); 
      } 
     } 
    } 
Смежные вопросы