在 ASP.NET MVC 中重写授权属性

我有一个 MVC 控制器基类,在其上应用 Authorize 属性,因为我希望几乎所有的控制器(以及它们的操作)都被授权。

然而,我需要有一个控制器和另一个控制器的行动未经授权。我想能够装饰他们与 [Authorize(false)]或东西,但这是不可用的。

有什么想法吗?

72312 次浏览

编辑: 因为 ASP.NET MVC 4最好的方法是简单地使用内置的 AllowAnonymous属性。

下面的答案是 ASP.NET MVC 的早期版本

您可以使用一个可选的 bool 参数创建一个从标准 AuthorizeAttribute 继承的自定义授权属性,以指定是否需要授权。

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

然后您可以使用这个属性来装饰您的基本控制器:

[OptionalAuthorize]
public class ControllerBase : Controller
{
}

对于任何不需要授权的控制器,只需使用‘ false’覆盖即可-例如。

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

我个人的看法是分割控制器。只需为不需要身份验证的操作创建另一个控制器。

或者你可以:


  • 不需要身份验证-在这里,您拥有所有的“基本资料”:)

  • 这里的所有操作都需要身份验证

这样,只需从特定类派生,就可以在需要时进行身份验证。

如果你只是想让一个操作在另外授权的控制器上是未经授权的,你可以这样做:

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