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

时间:2013-05-23 09:10:24

标签: asp.net-mvc authorize-attribute

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

4 个答案:

答案 0 :(得分:143)

你问:

  

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

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

详细

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

  1. 您想知道与方法相比如何对Action强制执行其他约束。例如
    • 在控制器级别,以“user”
    • 角色强制执行用户
    • 在操作级别,另外以“admin”
    • 角色强制执行用户
  2. 您想要在操作级别替换控制器约束
  3. 您希望在操作级别删除控制器约束,并使该方法对匿名用户可用
  4. 你没有指定你的MVC版本,所以我将假设今天的最新版本(MVC 4.5)。但是,即使您使用的是MVC 3,也不会改变答案。

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

    案例3.我不需要覆盖(使用[AllowAnonymous]),因为已经回答all over SOall over the web。我只想说:如果您在某个操作上指定[AllowAnonymous],即使控制器上有[Authorize],它也会将该操作公开。

    您还可以使整个网站受using a global filter授权,并对要公开的少数操作或控制器使用AllowAnonymous

    [Authorize]是附加的(案例1)

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

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

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

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

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

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

    覆盖[Authorize](案例2)

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

    解决此问题的一种方法是定义两个新属性,如下所示。 [OverrideAuthorize]除了[Authorize]之外什么都不做;它的唯一目的是定义一个我们可以检查的类型。 [DefaultAuthorize]允许我们检查请求中调用的Action是否使用[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);
        }
    }
    

    我们可以这样使用它:

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

    在上面的示例中,SuperusersIndex可用于具有“超级用户”角色的帐户,即使它没有“用户”角色。

答案 1 :(得分:41)

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

答案 2 :(得分:1)

我为ASP.NET Core 2.1改编了this answer's second case

与ASP.NET Core的AuthorizeAttribute的不同之处在于,您不必调用AuthorizeAttribute.OnAuthorization基本方法即可进行常规授权。这意味着,即使您没有显式调用base方法,基本AuthorizeAttribute仍然可以通过禁止访问来缩短授权。

我所做的是我创建了一个DefaultAuthorizeAttribute,它不是继承自AuthorizeAttribute,而是继承自Attribute。由于DefaultAuthorizeAttribute不继承自AuthorizeAttribute,因此我不得不重新创建授权行为。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class DefaultAuthorizeAttribute : Attribute, IAuthorizationFilter
{
    private readonly AuthorizeFilter m_authorizeFilter;

    public DefaultAuthorizeAttribute(params string[] authenticationSchemes)
    {
        var policyBuilder = new AuthorizationPolicyBuilder()
            .AddAuthenticationSchemes(authenticationSchemes)
            .RequireAuthenticatedUser();
        m_authorizeFilter = new AuthorizeFilter(policyBuilder.Build());
    }

    public void OnAuthorization(AuthorizationFilterContext filterContext)
    {
        if (filterContext.ActionDescriptor is ControllerActionDescriptor controllerAction
            && controllerAction.MethodInfo.GetCustomAttributes(typeof(OverrideAuthorizeAttribute), true).Any())
        {
            return;
        }
        m_authorizeFilter.OnAuthorizationAsync(filterContext).Wait();
    }
}

public class OverrideAuthorizeAttribute : AuthorizeAttribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationFilterContext filterContext) { }
}

答案 3 :(得分:0)

如果在控制器上使用它,那么该控制器的所有方法都将受到影响。

[Authorize]
public class SomeController(){

    // all actions are effected
    public ActionResult Action1
    public ActionResult Action2

如果您想阻止其中一项操作,可以使用以下内容:

[Authorize]
public class SomeController(){

    // all actions are effected
    public ActionResult Action1
    public ActionResult Action2

    [AllowAnonymous]
    public ActionResult Action3 // only this method is not effected...