Asp.net MVC4:授权控制器和动作

fra*_*ank 71 asp.net-mvc authorize-attribute

如果我在控制器和动作上都有Authorize属性,哪一个会起作用?或者都会生效?

And*_*own 149

您询问:

如果我在控制器和动作上都有Authorize属性,哪一个会起作用?都?

简单地回答这个问题:两者.效果是AND两个限制在一起.我将在下面解释原因......

细节

所以,有几个理由你可以问这个.

  1. 您想知道与方法相比如何对Action强制执行其他约束.例如
    • 在控制器级别,以"用户"角色强制执行用户
    • 在操作级别,另外强制执行"admin"角色的用户
  2. 您想要在操作级别替换控制器约束
  3. 您希望在操作级别删除控制器约束,并使该方法可供匿名用户使用

你没有指定你的MVC版本,所以我将假设今天的最新版本(MVC 4.5).但是,即使您使用的是MVC 3,也不会改变答案.

[Anonymous]覆盖控制器[Authorize](案例3)

案例3.我不需要覆盖(使用[AllowAnonymous]),因为它已经在所有SO整个网络上得到了回答.我只想说:如果你指定[AllowAnonymous]一个动作,它将使该动作公开,即使控制器已经[Authorize]在它上面.

您还可以使用全局过滤器使整个网站受到授权,并使用AllowAnonymous您要公开的少数操作或控制器.

[Authorize] 是添加剂(案例1)

案例1很简单.以下面的控制器为例:

[Authorize(Roles="user")]
public class HomeController : Controller {
    public ActionResult AllUsersIndex() {
        return View();
    }

    [Authorize(Roles = "admin")]
    public ActionResult AdminUsersIndex() {
        return View();
    }
}
Run Code Online (Sandbox Code Playgroud)

默认情况下[Authorize(Roles="user")],Controller中的所有操作仅对"用户"角色的帐户可用.因此,要访问AllUsersIndex您必须处于"用户"角色.但是要访问,AdminUsersIndex您必须同时处于"用户"和"管理员"角色.例如:

  • 用户名:Bob,角色:用户,无法访问AdminUsersIndex,但可以访问AllUsersIndex
  • 用户名:Jane,角色:admin,无法访问AdminUsersIndexAllUsersIndex
  • 用户名:Tim,角色:用户和管理员,可以访问AdminUsersIndexAllUsersIndex

这表明该[Authorize]属性是附加的.对于Users属性的属性也是如此,可以将其组合Roles以使其更具限制性.

此行为是由于控制器和操作属性的工作方式.属性链接在一起并应用于订单控制器然后操作.如果第一个拒绝授权,则控制返回并且不调用操作的属性.如果第一个通过授权,则也检查第二个授权.您可以通过指定Order(例如[Authorize(Roles = "user", Order = 2)])来覆盖此顺序.

覆盖[Authorize](案例2)

案例2比较棘手.回想一下[Authorize],按顺序检查属性(全局然后是控制器然后是动作).第一个检测到用户没有资格获得授权的人获胜,其他人则没有被调用.

解决此问题的一种方法是定义两个新属性,如下所示.该[OverrideAuthorize]做无非推迟到其他[Authorize]; 它的唯一目的是定义一个我们可以检查的类型.将[DefaultAuthorize]允许我们检查,看看是否行动被称为请求都装饰着[OverrideAuthorize].如果是,那么我们遵循Action授权检查,否则我们继续进行Controller级别检查.

public class DefaultAuthorizeAttribute : AuthorizeAttribute {
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        var action = filterContext.ActionDescriptor;
        if (action.IsDefined(typeof(OverrideAuthorizeAttribute), true)) return;

        base.OnAuthorization(filterContext);
    }
}
public class OverrideAuthorizeAttribute : AuthorizeAttribute {
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我们可以像这样使用它:

[DefaultAuthorize(Roles="user")]
public class HomeController : Controller {
    // Available to accounts in the "user" role
    public ActionResult AllUsersIndex() {
        return View();
    }
    // Available only to accounts both in the "user" and "admin" role
    [Authorize(Roles = "admin")]
    public ActionResult AdminUsersIndex() {
        return View();
    }
    // Available to accounts in the "superuser" role even if not in "user" role
    [OverrideAuthorize(Roles = "superuser")]
    public ActionResult SuperusersIndex() {
        return View();
    }
}
Run Code Online (Sandbox Code Playgroud)

在上面的示例SuperusersIndex中,即使没有"用户"角色,也可以使用具有"超级用户"角色的帐户.

  • 在MVC5中,只需在[this answer](http://stackoverflow.com/a/32661139/1861445)中描述的操作中添加`[OverrideAuthorization]`属性即可完成案例2. (4认同)

小智 43

我想在Overriding [Authorize](案例2)中添加一些内容

OverrideAuthorizeAttribute和DefaultAuthorizeAttribute工作正常,但我发现您还可以使用OverrideAuthorizationAttribute来覆盖在更高级别定义的授权过滤器.

[Authorize(Roles="user")]
public class HomeController : Controller {
    // Available to accounts in the "user" role
    public ActionResult AllUsersIndex() {
        return View();
    }
    // Available only to accounts both in the "user" and "admin" role
    [Authorize(Roles = "admin")]
    public ActionResult AdminUsersIndex() {
        return View();
    }
    // Available to accounts in the "superuser" role even if not in "user" role
    [OverrideAuthorization()]
    [Authorize(Roles = "superuser")]
    public ActionResult SuperusersIndex() {
        return View();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 需要MVC 5. (2认同)