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

在ASP.NET MVC中重写授权属性,.net,asp.net-mvc,security,authentication,authorize,.net,Asp.net Mvc,Security,Authentication,Authorize,我有一个MVC控制器基类,在这个基类上我应用了Authorize属性,因为我希望几乎所有的控制器(及其操作)都得到授权 但是,我需要有一个控制器和另一个未经授权的控制器的行动。我希望能够用[Authorize(false)]或其他东西装饰它们,但这不可用 有什么想法吗?编辑:由于ASP.NET MVC 4,最好的方法就是简单地使用内置属性 下面的答案是指ASP.NET MVC的早期版本 您可以创建一个自定义授权属性,该属性继承自标准AuthorizeAttribute,并带有可选的bool参数,

我有一个MVC控制器基类,在这个基类上我应用了Authorize属性,因为我希望几乎所有的控制器(及其操作)都得到授权

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


有什么想法吗?

编辑:由于ASP.NET MVC 4,最好的方法就是简单地使用内置属性

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

您可以创建一个自定义授权属性,该属性继承自标准AuthorizeAttribute,并带有可选的bool参数,以指定是否需要授权

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

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

或者你可以:

  • BaseController

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

  • BaseAuthController:BaseController

    此处的所有操作都需要身份验证


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

如果您只希望一个操作在其他授权的控制器上未经授权,则可以执行以下操作:

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);
            }
        }
    }
}
public类RequiresAuthorizationAttribute:ActionFilterAttribute
{
私有只读bool\u授权;
public RequiresAuthorizationAttribute()
{
_授权=真;
}
public RequiresAuthorizationAttribute(bool授权)
{
_授权=授权;
}
公共覆盖无效OnActionExecuting(ActionExecutingContext filterContext)
{
var overridingAttributes=filterContext.ActionDescriptor.GetCustomAttributes(typeof(requireAuthorizationAttribute),false);
如果(overridingAttributes.Length>0&&overridingAttributes[0]作为requireAuthorizationAttribute!=null&!((requireAuthorizationAttribute)overridingAttributes[0])。\u authorize
返回;
如果(授权)
{
//如果未通过身份验证,则重定向
如果(!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
//使用重定向的当前url
var redirectOnSuccess=filterContext.HttpContext.Request.Url.AbsolutePath;
//将它们发送到登录页面
//var redirectUrl=string.Format(“?redirectUrl={0}”,redirectOnSuccess);
var loginUrl=LinkBuilder.BuildUrlFromExpression(filterContext.RequestContext,RouteTable.Routes,
x=>x.Login(重定向成功));
filterContext.HttpContext.Response.Redirect(loginUrl,true);
}
}
}
}

ASP.NET MVC 4似乎通过添加属性“修复”了这一问题

:


我已经想到了这一点,但我希望有一个更简单的解决办法。但是,如果“他们”没有提供,那么您的解决方案是最好的。最好使用
[AllowAnonymous]
属性。等等。。。那么控制器只尊重某个特定类型的顶级类的属性?你知道为什么使用AllowAnonymous会更好吗?因为你有更好的控制力。在我的例子中,我希望仅对某些环境禁用授权端点,例如,localhost不需要它。这提供了一个比我在startup.cs中要做的更优雅的解决方案。11年后我们在这里讨论。
[Authorize]
public class AccountController : Controller
{
    [AllowAnonymous]
    public ActionResult Login()
    {
        // ...
    }

    // ...
}