Anular el atributo de autorización en ASP.NET MVC

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

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

¿Algunas ideas?

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

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

Puede crear un atributo de autorización personalizado que hereda de AuthorizeAttribute estándar con un parámetro bool opcional para especificar si se requiere autorización o no.

 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); } } 

Entonces puedes decorar tu controlador base con ese atributo:

 [OptionalAuthorize] public class ControllerBase : Controller { } 

y para cualquier controlador que no quiera autorización simplemente use la anulación con un ‘falso’ – por ejemplo

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

Parece que ASP.NET MVC 4 ‘corrigió’ esto al agregar un atributo AllowAnonymous .

David Hayden escribió sobre esto :

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

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

O podrías tener:

  • BaseController
    no requiere autenticación, aquí tienes todas tus “cosas básicas” :).

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

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

Si solo quiere que una acción no esté autorizada en un controlador 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(filterContext.RequestContext, RouteTable.Routes, x => x.Login(redirectOnSuccess)); filterContext.HttpContext.Response.Redirect(loginUrl, true); } } } }