覆盖ASP.NET MVC中的授权属性

And*_*nea 82 .net security authentication asp.net-mvc authorize

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

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

有任何想法吗?

Ste*_*ock 99

编辑:自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);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用该属性修饰基本控制器:

[OptionalAuthorize]
public class ControllerBase : Controller
{
}
Run Code Online (Sandbox Code Playgroud)

对于任何你不想要授权的控制器,只需使用带有'false'的覆盖 - 例如

[OptionalAuthorize(false)]
public class TestController : ControllerBase
{
    public ActionResult Index()
    {
        return View();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 最好使用`[AllowAnonymous]`属性. (2认同)

And*_*nea 75

似乎ASP.NET MVC 4通过添加AllowAnonymous属性来"修复"此问题.

大卫海登写到这个:

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

    // ...
}
Run Code Online (Sandbox Code Playgroud)


sir*_*cco 15

我个人对此的看法是拆分控制器.只需创建另一个控制器对于您不需要身份验证的操作.

或者你可以:

  • BaseController
    不需要身份验证 - 在这里你有你所有的"基础东西":).

  • BaseAuthController : BaseController
    此处的所有操作都需要验证

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


pon*_*tic 6

如果您只想在其他授权的控制器上对一个操作进行未授权,您可以执行以下操作:

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);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)