【问题标题】:Extended authorization when group can be disabled可以禁用组时的扩展授权
【发布时间】:2021-09-01 19:06:05
【问题描述】:

我正在编写一个 .net core 3.1 API 应用程序并在应用程序中实现了授权。它是通过 IPolicyRequirement 和 AuthorizationHandler 完成的。

services.AddAuthorizationCore(options =>
                              {
                                  AddPolicy(options, new UserRequirement());
                              });

services.AddTransient<IAuthorizationHandler, UserHandler>();

所需的控制器用Authorize 属性修饰。

    [ApiController]
    [Authorize(Policy = UserRequirement.Policy)]
    [Route("/api/[controller]")]
    public class TeamDetailsController : ControllerBase
    {
        ...
    }

一切正常,并在指定的地方限制对控制器调用的访问。

现在我需要根据帐户所属的团队是否启用来限制访问。因此,如果团队被禁用,人们可以登录,但无法访问大多数端点。

他们仍然应该能够访问某些端点,否则他们将无法采取业务指定的操作来重新启用团队。不允许任何角色调用该端点 - 仅由授权策略指定。

我也可以通过策略要求来做到这一点,但现在我想要一个带有 403 的特定错误消息,因此,API 调用者可以将基于角色的 403 与团队禁用的 403 不同。我认为 403 是这两种情况的理想代码因为在这两种情况下都禁止访问指定的端点,在某些情况下只是出于与角色无关的原因。

所以,总而言之,我需要返回 403 并带有来自策略要求的消息,例如:

public class UserHandler : AuthorizationHandler<UserRequirement>
{
    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                                         UserRequirement requirement)
    {
        var authenticatedUser = GetUserFromClaims();
        if (!await TeamIsEnabled(authenticatedUser))
        {
            context.Resource.Result = new JsonResult("Custom message");
            return;
        }

        if (!await RoleIsAllowed())
            return;

        context.Succeed(requirement);
    }
}

上面的代码不能作为内容工作。资源是RouteEndpoint 类型并且没有要发送的结果属性。

我的问题是:

  • 根据行业标准,我使用策略要求禁用基于授权策略要求的资源访问的方法是否正确?
  • 如果是这样,我如何返回团队禁用 403 的消息?
  • 如果禁用团队时不应返回 403,应该是什么代码?我不想返回 409 Conflict,因为它用于 db 并发异常。

我应该使用中间件和 IAsyncResultFilter 吗?我可以使用它,但我想我应该问问社区我是否可以逃脱

谢谢。

【问题讨论】:

  • 我认为你应该使用中间件,这样你就可以返回403。

标签: c# .net-core authorization asp.net-core-3.1 asp.net-core-middleware


【解决方案1】:

所以,最后我把它们分成了 2 位:

  • 实现 IAsyncAuthorizationFilter 以处理组开/关的过滤器,返回 400 和错误详细信息,因为我无法使过滤器返回 403 和消息。
  • 实现 AuthorizationHandler 以限制对特定用户的访问的处理程序,并且要求实现 IPolicyRequirement。

startup.cs 我们有:

services.AddControllers(opt =>
{
 ...
 opt.Filters.Add<GroupIsEnabledFilter>();
 ...
});

services.AddAuthorizationCore(options =>
{
 AddPolicy(options, new MaintainerRequirement());
 AddPolicy(options, new SuperUserRequirement());
})
...
;

services.AddTransient<IAuthorizationHandler, MaintainerHandler>();
services.AddTransient<IAuthorizationHandler, SuperUserHandler>();

过滤器模板可能是这样的:

public class GroupIsEnabledFilter : IAsyncAuthorizationFilter
{
  public GroupIsEnabledFilter(...)
  {
      ...
      //inject your dependencies here
      ...
  }
  
  public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
  {
    if (AllowsDisabledGroup(context)) //use context.ActionDescriptor.EndpointMetadata to get endpoint details
        return;
  
    var group = _authService.GetGroupId();
    if (await GroupIsActive(group))
        return;
  
    var problemDetails = new ProblemDetails
    {
    ...
    };
  
    context.Result = new ObjectResult(problemDetails)
    {
        ContentTypes = new MediaTypeCollection { new MediaTypeHeaderValue("application/json") },
        StatusCode = StatusCodes.Status400BadRequest
    };
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-16
    • 1970-01-01
    • 2019-02-04
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多