【问题标题】:How to skip Authorization on a particular action method?如何跳过特定操作方法的授权?
【发布时间】:2021-10-11 12:18:00
【问题描述】:

下面的代码检查控制器中所有操作方法的授权。我正在使用 Asp.NET Core 2.2

授权属性

public class AuthorizeRolesAttribute : AuthorizeAttribute
{
    public AuthorizeRolesAttribute(params string[] roles) : base()
    {
        Roles = string.Join(",", roles);
    }
}

控制器

[AuthorizeRoles(Roles.Worker,Roles.Contractor)]
public class MyController:Controller
{
    [HttpGet]
    public ActionResult Index()
    {
       return View();
    }

    [HttpPost]
    public ActionResult Action1()
    {
       return View();
    }

    [HttpPost]
    public ActionResult Action2()
    {
       return View();
    }

}

我想在应用特定属性时跳过Index 操作方法的授权。 [AllowAnonymous] 属性的工作方式相同。但是我认为[AllowAnonymous] 将允许未经身份验证的用户。我不希望未经身份验证的用户访问索引。我还试图避免在单个操作方法上应用 Authorize 属性。

所以控制器是

[AuthorizeRoles(Roles.Worker,Roles.Contractor)]
public class MyController:Controller
{
    [IgnoreAthorization]
    [HttpGet]
    public ActionResult Index()
    {
       return View();
    }

    [HttpPost]
    public ActionResult Action1()
    {
       return View();
    }

    [HttpPost]
    public ActionResult Action2()
    {
       return View();
    }

}

更新 1
当操作用[IgnoreAuthorization] 属性修饰时,策略构建器中是否有办法根据授权跳过角色。这是我在 startup.cs 中的当前政策。我正在使用 OpenID Connect 进行身份验证

var authorizationPolicy = new AuthorizationPolicyBuilder()
           .RequireClaim(ClaimTypes.Email)
           .RequireClaim(ClaimTypes.NameIdentifier)
           .RequireClaim(ClaimTypes.Name)
           .RequireClaim(IdentityClaimTypes.IdToken)               
           .RequireAuthenticatedUser()
           .Build();           

        // mvc
        services.AddMvc(options =>
        {
            options.Filters.Add(new AuthorizeFilter(authorizationPolicy));
        })

更新 2
尝试添加自定义 AuthorizeFilter 但没有用

public class MyAuthorizeFilter : AuthorizeFilter
{
    public MyAuthorizeFilter(AuthorizationPolicy policy)
        : base(policy)
    {
    }

    public override Task OnAuthorizationAsync(AuthorizationFilterContext context)
    {
        var skip = context.ActionDescriptor.EndpointMetadata.Any(x => x is IgnoreAthorization) &&
            context.HttpContext.User.Identity.IsAuthenticated;

        if (skip)
        {
            return Task.CompletedTask;
        }

        return base.OnAuthorizationAsync(context);
    }
}

然后在startup.cs中添加MyAuthorizeFilter

   // mvc
    services.AddMvc(options =>
    {
        options.Filters.Add(new MyAuthorizeFilter(authorizationPolicy));
    })

【问题讨论】:

  • 如果将[AuthorizeRoles()] 添加到Index 会发生什么?
  • 或者,只需在控制器上使用[Authorize],在任何不是Index的操作上使用[AuthorizeRoles(...)]
  • 如果我在控制器上保留[AuthorizeRoles(Roles.Worker,Roles.Contractor)] 并在索引上添加[AuthorizeRoles()],索引操作仍会获得角色授权。在每个操作上添加[AuthorizeRoles(...)] 仍然是一种选择,但我试图避免这种情况。我想要角色授权的整个控制器,除了索引
  • 是的,我很确定这是您现在唯一的选择。 MVC5 曾经有一个 OverrideAuthorization 属性,但从未被引入。
  • 有没有办法在策略生成器中处理这个问题?查看我的更新 1

标签: c# asp.net-core asp.net-core-2.1 asp.net-authorization .net-core-authorization


【解决方案1】:

对于多策略评估,如果您将多个策略应用于控制器或操作,则必须通过所有策略才能授予访问权限。

在您的场景中,您希望经过身份验证的用户访问索引页面,并希望基于角色的用户访问其他操作。如果给控制器设置策略,然后在action方法上使用另一个策略,它会先检查Controller的策略,然后检查Action的策略。

因此,根据您的情况,唯一的方法是设置至少两项策略,一项针对经过身份验证的用户,一项针对基于角色的用户。然后,应用以下策略:

public class MyController:Controller
{ 
     [Authorize(policy: "EveryOne")]
     public ... Index(){
     }
    [HttpPost]
    [Authorize(policy: "Role")]
    public ActionResult Action1()
    {
       return View();
    }

    [HttpPost]
    [Authorize(policy: "Role")]
    public ActionResult Action2()
    {
       return View();
    }
 }

更多详细信息,请参考以下文章:

Multiple Policy Evaluation

Authorize Attribute should have a flag to Override previous Authorize Attributes Controller - Method

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 2015-06-21
    • 1970-01-01
    • 1970-01-01
    • 2017-12-13
    相关资源
    最近更新 更多