2010-07-30 3 views
7

Aggiornato: Grazie all'aiuto qui ho creato la seguente soluzione:chiede all'utente di accedere invece dell'accesso negato?

public class CustomAuthorize : AuthorizeAttribute 
{ 
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
    { 
     // Returns HTTP 401 - see comment in HttpUnauthorizedResult.cs 
     // If user is not logged in prompt 
     if (!filterContext.HttpContext.User.Identity.IsAuthenticated) 
     { 
      base.HandleUnauthorizedRequest(filterContext); 
     } 
     // Otherwise deny access 
     else 
     { 
      filterContext.Result = new RedirectToRouteResult(
       new RouteValueDictionary { 
       {"controller", "Account"}, 
       {"action", "NotAuthorized"} 
      }); 
     } 
    } 
} 

ho iniziato da NerdDinner e sto usando FormsAuthentication con ActiveDirectory come il mio provider di appartenenza. Ho aggiunto il supporto per i ruoli tramite il mio db con Global.asax & AccountController (sotto).

Così ora nel mio controller ho il mio attributo Autorizza impostato solo sui ruoli di admin (sotto). Il mio utente che ha effettuato l'accesso è un autore. Quando faccio clic su Elimina mi chiede di accedere anche se l'ho già fatto. Dove posso inserire la logica per restituire una vista negata dell'accesso?

Global.asax.cs

protected void Application_AuthenticateRequest(Object sender, EventArgs e) 
    { 
     HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName]; 
     if (authCookie == null || authCookie.Value == "") 
     { 
      return; 
     } 

     FormsAuthenticationTicket authTicket = null; 

     try 
     { 
      authTicket = FormsAuthentication.Decrypt(authCookie.Value); 
     } 
     catch 
     { 
      return; 
     } 

     if (Context.User != null) 
     { 
      string[] roles = authTicket.UserData.Split(new char[] { ';' }); 
      Context.User = new GenericPrincipal(Context.User.Identity, roles); 
     } 
    } 

AccountController.cs

[HttpPost] 
    [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)) 
     { 
      ViewData["rememberMe"] = rememberMe; 
      return View(); 
     } 

     // Make sure we have the username with the right capitalization 
     // since we do case sensitive checks for OpenID Claimed Identifiers later. 
     userName = this.MembershipService.GetCanonicalUsername(userName); 

     // Lookup user's (CWID) appropriate access level 
     string accessLevel = userRepository.FindUserByUserName(userName).AccessLevel.LevelName; 

     FormsAuthenticationTicket authTicket = new 
         FormsAuthenticationTicket(1, //version 
         userName, // user name 
         DateTime.Now,    //creation 
         DateTime.Now.AddMinutes(30), //Expiration 
         rememberMe, //Persistent 
         accessLevel); // hacked to use roles instead 

     string encTicket = FormsAuthentication.Encrypt(authTicket); 
     this.Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket)); 

     if (!String.IsNullOrEmpty(returnUrl)) 
     { 
      return Redirect(returnUrl); 
     } 
     else 
     { 
      return RedirectToAction("Index", "Home"); 
     } 
    } 

SpotlightController.cs

[Authorize(Roles="Admin")] 
    public ActionResult Delete(int id) 

risposta

5

Ecco ciò che AuthorizeAttribute fa, immediatamente: Controlla se l'utente corrente è autorizzato per la richiesta corrente e restituisce HHTP 401/UNAUTHORIZED se non lo sono, perché non sono registrati in tutto o non sono nell'elenco di utenti/ruoli autorizzati per la richiesta corrente.

Web forms authentication HTTP module sees this 401 response, intercepts that, and turns it into an HTTP 302 (redirect) response to the login page, se l'attributo loginUrl è configurato in web.config. Il pensiero generale è che se un utente è negato l'accesso al sito perché non è loggato, ma la prossima cosa che vorranno fare è accedere.

Poiché quello che vuoi fare è ridirezionare altrove, suggerimento di Hal di sovrascrivere HandleUnauthorizedRequest e il reindirizzamento non è irragionevole. Ricorda che se vuoi che gli utenti non autenticati visualizzino la pagina di accesso (invece che autenticata, ma non nell'elenco di utenti/ruoli consentiti), dovrai aggiungere la logica per farlo. Vorrei sconsigliare l'idea di scavalcare AuthorizeCore o OnAuthorization; nessuno di questi in realtà risolve il problema e sono molto più facili da rovinare rispetto a HandleUnauthorizedRequest.

+0

Craig ha assolutamente ragione: dovresti gestire l'eccezione di un ruolo rispetto a un utente non autenticato. Non penso che sarebbe troppo difficile, ma non l'ho provato in modo YMMV. Anch'io sconsiglio di fare confusione con AuthorizeCode o OnAuthorization a meno che tu non voglia veramente implementare il tuo schema di autenticazione. – Hal

+0

Ho bisogno di leggere di più. Nel frattempo potrei usare qualche aiuto per sovrascrivere HandleUnauthorizedRequest. Capisco come eseguire il rollover della mia classe che eredita da AuthorizeAttribute e quindi eseguire l'override di HandleUnauthorizedRequest. Non ho bisogno del mio attributo dato che questa è l'unica cosa che sta cambiando. Quindi, come sovrascrivere HandleUnauthorizedRequest senza derivare? – ryan

+0

È necessario derivare un nuovo tipo e sovrascrivere quel metodo. Ma quel metodo è l'unica cosa che devi cambiare. –

2

Suppongo che si possa derivare da AuthorizeAttribute e poi ignorare HandleUnauthorizedRequest e mettere la vostra la propria logica di reindirizzamento lì.

Grazie,

Hal

+0

Immagino che mi manchi il motivo per cui HandleUnauthorizedRequest non fa nulla ora? O non sto semplicemente catturando quell'evento? – ryan

+0

L'utente che ha effettuato l'accesso in un diritto autore, non un amministratore? Il comportamento desiderato è che un utente con privilegi insufficienti venga reindirizzato a una pagina di eccezione, non a una pagina che tenta di accedere con credenziali elevate (che credo sia il comportamento predefinito). Sto comprendendo correttamente? – Hal

+0

Questo è corretto! – ryan

1

In alternativa si possono ignorare l'attributo Autorizza. Sostituirai il metodo OnAuthorization e otterrai il risultato dal metodo AuthorizeCore dalla tua base. In base a tale risultato è possibile generare un'eccezione o un'eccezione personalizzata (ad esempio un'eccezione di sicurezza personalizzata che registra lo stato) direttamente da OnAuthirziation.