覆盖ASP.NET MVC中的授权属性
我有一个MVC控制器基类,我应用了授权属性,因为我想几乎所有的控制器(和他们的行动一起)被授权。
不过,我需要有一个控制器和另一个控制器的行动未经授权。 我想能够用[Authorize(false)]
来装饰它们,但是这是不可用的。
有任何想法吗?
编辑:由于ASP.NET MVC 4最好的方法是简单地使用内置的AllowAnonymous属性。
下面的答案是指早期版本的ASP.NET MVC
您可以使用可选的bool参数来创build从标准AuthorizeAttributeinheritance的自定义授权属性,以指定是否需要授权。
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 { }
而对于任何不需要授权的控制器,只需使用带有“假”的覆盖 – 例如
[OptionalAuthorize(false)] public class TestController : ControllerBase { public ActionResult Index() { return View(); } }
看来ASP.NET MVC 4通过添加一个AllowAnonymous属性来“修复”这个问题。
大卫·海登写道 :
[Authorize] public class AccountController : Controller { [AllowAnonymous] public ActionResult Login() { // ... } // ... }
我个人认为这将是分裂控制器。 只需创build另一个控制器对于您不需要身份validation的操作。
或者你可以有:
-
BaseController
不需要authentication – 在这里你有所有的“基本东西”:)。 -
BaseAuthController : BaseController
这里的所有操作都需要authentication
这样,你可以在需要时进行身份validation,只需从特定的类派生。
如果你只想要一个行动是未经授权的控制器未经授权,你可以做这样的事情:
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); } } } }