2009-09-17 1 views
12

Sto utilizzando un ActionFilterAttribute per eseguire la logica di autenticazione personalizzata. L'attributo verrà utilizzato solo su una classe Controller derivata che contiene la mia logica di autenticazione.ActionFilterAttribute - si applica alle azioni di un tipo di controller specifico

Ecco il mio controller, derivato dalla mia classe di controllo personalizzato, e un attributo di esempio:

public class MyController : CustomControllerBase 
{ 

    [CustomAuthorize(UserType = UserTypes.Admin)] 
    public ActionResult DoSomethingSecure() 
    { 
     return View(); 
    } 

} 

Ecco un esempio del mio ActionFilterAttribute:

public class CustomAuthorizeAttribute : ActionFilterAttribute 
{ 
    public MyUserTypes UserType { get; set; } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     myUser user = ((CustomControllerBase)filterContext.Controller).User; 

     if(!user.isAuthenticated) 
     { 
     filterContext.RequestContext.HttpContext.Response.StatusCode = 401; 
     } 
    } 
} 

funziona alla grande.

Ecco la domanda: Posso richiedere che questo attributo venga utilizzato SOLO su Azioni nel mio tipo di controller personalizzato?

+1

Il tuo attributo è danneggiato perché non eredita da AuthroizeAttribute e pertanto non è garantito l'esecuzione quando l'azione viene memorizzata nella cache. Vedi http://blogs.teamb.com/craigstuntz/2009/09/09/38390/ per le soluzioni che funzionano con il caching. –

+0

Perché il risultato dell'azione dovrebbe essere memorizzato nella cache? –

+0

Sarebbe memorizzato nella cache perché qualcuno ha detto di essere memorizzato nella cache. Immagina che qualcuno inserisca l'attributo Cache in una classe genitore, senza notare l'attributo rotto nel sottotipo. È un'idea molto migliore utilizzare un attributo che non sia fondamentalmente incompatibile con la memorizzazione nella cache di ASP.NET/MVC. Vedi il link sopra per le opzioni. –

risposta

14

È possibile inserire ActionFilter sulla classe stessa. Tutte le azioni della classe realizzeranno ActionFilter.

[CustomAuthorize] 
public class AuthorizedControllerBase : CustomControllerBase 
{ 
} 

public class OpenAccessControllerBase : CustomControllerBase 
{ 
} 

public class MyRealController : AuthorizedControllerBase 
{ 
    // GET: /myrealcontroller/index 
    public ActionResult Index() 
    { 
     return View(); 
    } 
} 
+0

Sto solo andando a definire ActionFilter all'interno della classe (quindi non è disponibile su altre classi.) È bello sapere che l'attributo può essere definito su TUTTI i RISULTATI Azione in un controller. –

7

Sulla base dei commenti e dei vincoli del mio sistema, ho adottato un approccio ibrido. Fondamentalmente, se la richiesta arriva attraverso una rotta memorizzata nella cache o se l'Utente non è impostato per nessuna ragione, l'autenticazione fallisce nel modo corretto.

public class CustomAuthorizeAttribute : AuthorizeAttribute 
{ 
    private MyUser User { get; set; } 

    public override void OnAuthorization(AuthorizationContext filterContext) 
    { 
    //Lazy loads the user in the controller. 
    User = ((MyControllerBase)filterContext.Controller).User; 

    base.OnAuthorization(filterContext); 
    } 

    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
    bool isAuthorized = false; 
    string retLink = httpContext.Request.Url.AbsolutePath; 

    if(User != null) 
    { 
     isAuthorized = User.IsValidated; 
    } 

    if (!isAuthorized) 
    { 
     //If the current request is coming in via an AJAX call, 
     //simply return a basic 401 status code, otherwise, 
     //redirect to the login page. 
     if (httpContext.Request.IsAjaxRequest()) 
     { 
     httpContext.Response.StatusCode = 401; 
     } 
     else 
     { 
     httpContext.Response.Redirect("/login?retlink=" + retLink); 
     } 
    } 

    return isAuthorized; 
    } 
} 
+0

Se stai reindirizzando un caso "isAuthorized = false", allora perché non restituisci true alla fine? – Alex

+0

Nel caso del flusso IsAjaxRequest, l'utente non viene reindirizzato, quindi il metodo deve ancora tornare. –

+0

+1 per usare AuthorizeAttribute invece di ActionFilterAttribute. Risolve il problema che l'azione del controller con l'attributo CustomAuthotize viene eseguita anche se non è stato effettuato l'accesso che potrebbe causare altri problemi. –