2009-12-08 14 views
7

Ho il seguente codice che ho digitato nell'account Controller nel mio progetto MVC e sono sia nel ruolo di amministratore che di gestione. Quando effettuo l'accesso, viene reindirizzato al mio indice home anziché essere reindirizzato al mio indice AdminApp. Qualche idea su dove sto andando male nel mio codice?In che modo è possibile modificare il reindirizzamento di accesso di ASP.Net MVC in base al ruolo?

[AcceptVerbs(HttpVerbs.Post)] 
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", 
     Justification = "Needs to take same parameter type as Controller.Redirect()")] 
    public ActionResult LogOn(string userName, string password, bool rememberMe, string returnUrl) 
    { 

     if (!ValidateLogOn(userName, password)) 
     { 
       return View(); 
     } 

     FormsAuth.SignIn(userName, rememberMe); 
     if (!String.IsNullOrEmpty(returnUrl)) 
     { 
      return Redirect(returnUrl); 
     } 
     else 
     { 
      if (User.IsInRole("Administrator") || (User.IsInRole("Manager"))) 
      { 
       return RedirectToAction("Index", "AdminApp"); 
      } 
      else 
      { 
       return RedirectToAction("Index", "Home"); 
      } 

     } 
    } 

risposta

19

Il motivo per cui il codice non funziona come previsto è perché il User non è stato ufficialmente registrato e autenticato. Che cosa? Ma hai chiamato SignIn!

FormsAuth.SignIn(userName, rememberMe); - che in questo caso è solo un wrapper per FormsAuthentication.SetAuthCookie(userName, createPersistentCookie); - imposta solo il cookie di autorizzazione asp.net sul browser degli utenti come parte della risposta. È solo per le richieste dopo il questo punto che il browser dell'utente avrà il cookie, facendo sì che l'appartenenza asp.net configuri correttamente l'oggetto "Utente". Tutto il codice nel metodo LogOn presuppone ancora un utente anonimo, pertanto il controllo IsInRole non riesce e si viene reindirizzati a casa. Metti la tua dichiarazione if su un'altra pagina e dopo aver effettuato l'accesso, vedrai che ora User.IsInRole funziona come previsto. (E in effetti, questo è ciò che useresti per User.IsInRole, ma non durante il processo di accesso)

Quindi, come controllare durante l'effettivo processo di accesso? Roles.IsUserInRole o Roles.GetRolesForUser sono un paio di modi, ad esempio .:

if (Roles.IsUserInRole(userName, "Administrator") || Roles.IsUserInRole(userName, "Administrator")) 
{ 
    return RedirectToAction("Index", "AdminApp"); 
} 

È necessario specificare esplicitamente il nome utente dell'utente login, che effettivamente eseguire una query contro il datastore appartenenza. In base a questa nota, credo che il codice precedente causerebbe di conseguenza l'esecuzione di due query, che potrebbero risultare non ideali. Questo è dove Roles.GetRolesForUser potrebbe essere un'opzione migliore:

string[] roles = Roles.GetRolesForUser(userName); 
if (roles.Contains("Administrator") || roles.Contains("Manager")) 
{ 
    return RedirectToAction("Index", "AdminApp"); 
} 

Sperare che aiuti!

+0

ha funzionato come un fascino! Apprezzo l'aiuto! – Ben

+0

Adesso sono passati 3 1/2 anni ma .. grazie! – peter

+0

Wow! Funziona ancora allo stesso modo per ** Asp.Net Core **. – vivek

0

È necessario annullare l'istruzione if. Rivedere i seguenti:

Modifica questo:

FormsAuth.SignIn(userName, rememberMe); 
if (!String.IsNullOrEmpty(returnUrl)) 
{    
    return Redirect(returnUrl); 
}   
else 
{ 
    if (User.IsInRole("Administrator") || (User.IsInRole("Manager"))) 
    {    
     return RedirectToAction("Index", "AdminApp");  
    } 
    else   
    {     
    return RedirectToAction("Index", "Home"); 
    }  
} 

a questo:

if (User.IsInRole("Administrator") || (User.IsInRole("Manager"))) 
{    
    return RedirectToAction("Index", "AdminApp");  
} 
else   
{     
return RedirectToAction("Index", "Home"); 
}  

Il problema è la linea if(!String.IsNullOrEmpty(returnUrl))) sta valutando True perché il parametro ReturnURL ha l'URL della pagina che si venuto da impostazione predefinita.

+0

hmm. Ho provato e non ha funzionato per me. Posso usare User.InInRole con successo su una pagina ASPX per mostrare/nascondere i collegamenti, ma non funziona quando ce l'ho in un controller. C'è un altro modo per farlo nel controller? – Ben

+0

Non dovrebbe fare molta differenza, ma puoi provare Roles.IsUserInRole(). Tuttavia, penso che questo sia lo stesso metodo che finisce per essere chiamato dal metodo User.IsInRole(). –

2

Sto utilizzando VS 2013 e il suo nuovo modello di identità, ho finito per andare con questo:

foreach (IdentityUserRole identityUserRole in user.Roles) 
{ 
    if (identityUserRole.RoleId == "AdminRoleId") 
    { 
    return RedirectToAction("Index", "Admin"); 
    } 
    else if (identityUserRole.RoleId == "MemberRoleId") 
    { 
    return RedirectToAction("Index", "Members"); 
    } 
} 
Problemi correlati