【问题标题】:How to enforce authorization checks in every controller method?如何在每个控制器方法中强制执行授权检查?
【发布时间】:2021-04-25 04:54:28
【问题描述】:

我正在我的 Web API 中实现 Resource-based authorization in ASP.NET Core

我想强制程序员在每个控制器方法中始终调用_authorizationService.AuthorizeAsync

如果某些控制器方法完成但没有至少调用一次 AuthorizeAsync,我如何确保返回 403 Unauthorized 响应?

我还可以考虑使用属性或其他方式将控制器方法显式标记为无需授权即可使用。主要思想是应用“全部拒绝,然后允许一些”的原则,并防止仅仅因为有人忘记添加AuthorizeAsync 调用而造成安全漏洞。

【问题讨论】:

  • 为什么要在操作方法中进行身份验证?只需使用[Authorize](或您自己的派生版本),您就可以强制将其应用于您的应用程序。
  • 如果这是适用于所有路由的一般授权要求,那么您应该调整默认策略以接受该要求,以便在您使用 [Authorize] 时自动发生。否则,您始终可以添加 MVC 授权过滤器。
  • @DavidG 我不能使用 [Authorize] 因为它不支持我需要的用例(引用微软文章:“如果您根据 CRUD(创建,读取、更新、删除)操作”...)。在这种情况下,基于资源的授权似乎是我对任何资源应用通用 CRUD 身份验证规则的最佳选择。

标签: asp.net-core asp.net-core-mvc authorization


【解决方案1】:

在您的应用程序中编码特定行为以防止编码实践非常奇怪。为什么不使用静态代码分析,例如 SonarQube 并创建自定义规则来执行此操作?

【讨论】:

  • 好主意,谢谢。唯一的缺点是它是团队中每个开发人员都必须了解并知道如何正确配置和使用的另一种工具。
【解决方案2】:

使用动作过滤器发明了一个快速而肮脏的解决方案。我在 HandleRequirementAsync 中执行以下操作:

    // add a flag to the context about the fact that authorization has been attempted
    // so that our custom ActionFilter can fail if programmer forgets to call authorization
    // on methods that are not explicitly marked with [AllowUnauthorized] attribute
    var httpContext = _httpContextAccessor.HttpContext;
    httpContext.Items.Add(AuthAttemptedMark, true);

My Handler 还有一个辅助函数来判断它是否被调用:

    public bool HasAuthorizationBeenAttemptedForRequest()
    {
        var httpContext = _httpContextAccessor.HttpContext;

        return httpContext.Items.ContainsKey(AuthAttemptedMark) &&
            (bool)httpContext.Items[AuthAttemptedMark];
    }

然后我有一个过滤器:

公共类 RequestAuthorizationAttemptGuardFilter : IActionFilter { CrudResourceAuthorizationUserClaimHandler _authHandler;

    public RequestAuthorizationAttemptGuardFilter(CrudResourceAuthorizationUserClaimHandler authHandler)
    {
        _authHandler = authHandler;
    }

    public void OnActionExecuting(ActionExecutingContext context)
    { }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // if the action did not have any authorization attempts
        // and was not marked as explicitly allowed,
        // then return forbidden
        if (!_authHandler.HasAuthorizationBeenAttemptedForRequest())
            context.Result = new ForbidResult();
    }
}

因此,如果我检测到程序员懒惰并忘记添加至少一个对授权服务的调用,则结果将替换为 403 Forbidden

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-13
    • 2017-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多