2009-04-14 13 views
77

Tengo una clase base de controlador MVC en la que apliqué el atributo Autorizar ya que deseo que casi todos los controladores (y sus acciones) estén autorizados.Anular Autorizar atributo en ASP.NET MVC

Sin embargo, necesito tener un controlador y una acción de otro controlador no autorizado. Quería poder decorarlos con el [Authorize(false)] o algo así, pero esto no está disponible.

¿Alguna idea?

Respuesta

70

Parece ASP.NET MVC 4 'fija' esto añadiendo un atributo AllowAnonymous.

David Hayden wrote about this:

[Authorize] 
public class AccountController : Controller 
{ 
    [AllowAnonymous] 
    public ActionResult Login() 
    { 
     // ... 
    } 

    // ... 
} 
96

Editar: Desde ASP.NET MVC 4 el mejor enfoque es simplemente usar el atributo incorporado AllowAnonymous.

La respuesta a continuación se refiere a las versiones anteriores de ASP.NET MVC

Se puede crear un atributo de autorización personalizado heredando de la AuthorizeAttribute de serie con un parámetro booleano opcional para especificar si se requiere o no la autorización.

public class OptionalAuthorizeAttribute : AuthorizeAttribute 
{ 
    private readonly bool _authorize; 

    public OptionalAuthorizeAttribute() 
    { 
     _authorize = true; 
    } 

    public OptionalAuthorizeAttribute(bool authorize) 
    { 
     _authorize = authorize; 
    } 

    protected override bool AuthorizeCore(HttpContextBase httpContext) 
    { 
     if(!_authorize) 
      return true; 

        return base.AuthorizeCore(httpContext); 
    } 
} 

A continuación, se puede decorar el controlador de base con ese atributo:

[OptionalAuthorize] 
public class ControllerBase : Controller 
{ 
} 

y para todos los controladores que no desea la autorización sólo tiene que utilizar la anulación con un 'falso' - por ejemplo,

[OptionalAuthorize(false)] 
public class TestController : ControllerBase 
{ 
    public ActionResult Index() 
    { 
     return View(); 
    } 
} 
+0

He pensado en esto, pero yo estaba esperando una solución más simple. Sin embargo, si "ellos" no proporcionaron uno, entonces su solución es la mejor. –

+2

Es mejor usar el atributo '[AllowAnonymous]'. – Jaider

+0

Espera ... ¿entonces el controlador solo respeta el atributo de la clase de nivel superior de un tipo particular? – Triynko

15

Mi opinión personal sobre esto sería dividir el controlador. Simplemente cree otro controlador. Para las acciones, no necesita autenticación.

O usted podría tener:

  • BaseController
    no requiere autenticación - Aqui tiene todas sus "cosas de base" :).

  • BaseAuthController : BaseController
    todas las acciones aquí requieren autenticación.

De esta manera puede tener la autenticación cuando lo desee, simplemente derivando de una clase específica.

6

Si lo que desea es una acción no autorizada en un controlador de otro modo autorizado, puede hacer algo como esto:

public class RequiresAuthorizationAttribute : ActionFilterAttribute 
{ 
    private readonly bool _authorize; 

    public RequiresAuthorizationAttribute() 
    { 
     _authorize = true; 
    } 

    public RequiresAuthorizationAttribute(bool authorize) 
    { 
     _authorize = authorize; 
    } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     var overridingAttributes = filterContext.ActionDescriptor.GetCustomAttributes(typeof (RequiresAuthorizationAttribute), false); 

     if (overridingAttributes.Length > 0 && overridingAttributes[0] as RequiresAuthorizationAttribute != null && !((RequiresAuthorizationAttribute)overridingAttributes[0])._authorize) 
      return; 

     if (_authorize) 
     { 
      //redirect if not authenticated 
      if (!filterContext.HttpContext.User.Identity.IsAuthenticated) 
      { 
       //use the current url for the redirect 
       var redirectOnSuccess = filterContext.HttpContext.Request.Url.AbsolutePath; 

       //send them off to the login page 
       //var redirectUrl = string.Format("?RedirectUrl={0}", redirectOnSuccess); 
       var loginUrl = LinkBuilder.BuildUrlFromExpression<HomeController>(filterContext.RequestContext, RouteTable.Routes, 
                        x => x.Login(redirectOnSuccess)); 
       filterContext.HttpContext.Response.Redirect(loginUrl, true); 
      } 
     } 
    } 
} 
Cuestiones relacionadas