【问题标题】:ASP.Net Core WebAPI Authorization Policy for User or Admin用户或管理员的 ASP.Net Core WebAPI 授权策略
【发布时间】:2019-09-11 00:53:10
【问题描述】:

我有一个返回用户数据的控制器。我想设置授权,以便管理员可以访问此控制器并为任何用户检索数据,而非管理员用户可以访问控制器并为自己检索数据。

我已排除使用[Authorize (Roles = "Admin")],因为这意味着用户无法获取自己的数据。所以我在控制器动作中插入了以下逻辑:

var userId = _httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.Name).Value;
var roles = _httpContextAccessor.HttpContext.User.FindAll(ClaimTypes.Role);

var query = roles.Select(r => r.Value).Contains("Admin");

Customer customer =await _context.Customers.FindAsync(id);

if (!(customer.EmailAddress == userId || query))
 return Unauthorized();

这大致相当于this Stack Overflow answer,但用于 ASP.Net Core 而不是 MVC。

我的问题是,有没有办法通过授权策略来做到这一点?添加 RequireRole 检查很简单,在 MS Documentation 以及无数博客中都有介绍,但我找不到或想出一种方法来使用策略来检查用户尝试访问的数据是否是他们自己的。

我确定这不是一个不常见的要求,有没有办法做到这一点,或者我目前正在做的事情还可以吗?我能想到的唯一其他方法是有两个单独的端点,但这两种选择似乎都不优雅。

【问题讨论】:

  • 用户返回他/她的数据,管理员返回所有用户的信息。它们是两种不同的功能,您可以使用两种不同的功能。如果管理员只想返回他自己的信息怎么办?
  • 用户返回他们的数据,用户是管理员并且只想返回他们自己的数据。好的,所以他们到达终点,给我用户 X 的数据。用户是否在请求用户 X 的信息?还是他们是管理员?如果其中一个为真,则返回数据。同样的逻辑适用,问题仍然存在——这可以通过授权策略来完成吗?
  • 另一种选择(可能是您所建议的)是让一个端点用 [Authorize(Roles="Admin")] 注释,它为任何用户提供数据,另一个只需要登录在用户中,它不允许您指定要为哪个用户提供数据,而是会在声明中查找用户并返回该用户的数据。这就是你的建议吗?根据我的问题,这似乎不优雅,似乎违反了 DRY 原则。

标签: c# asp.net-core jwt


【解决方案1】:

该策略用于授权,但管理员或普通用户都可以访问控制器,他们都是授权的。

这是您确定应返回哪些数据的自定义逻辑,与授权无关。如果您坚持使用策略,您可以将逻辑放到处理程序中,但是当逻辑在控制器中时,这没有任何改变:

public class CustomerHandler : AuthorizationHandler<CustomerRequirement>
{
    IHttpContextAccessor _httpContextAccessor = null;

    public CustomerHandler(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context,
                                               CustomerRequirement requirement)
    {

        HttpContext httpContext = _httpContextAccessor.HttpContext;

        //your logic 

        httpContext.Items["message"] = "ownData";

        context.Succeed(requirement);
        return Task.CompletedTask;
    }
}

并在控制器中读取,以便您知道是读取自己的数据还是所有用户的数据:

var message = HttpContext.Items["message"];

在我的选项中,在您的 Web api 中设置两个端点/功能,一个用于管理员,一个用于用户是干净的方式。此外,您的客户端应用程序有责任确定当前用户想要返回他自己的数据还是所有用户的数据。向 web api 发送请求并让 api 由逻辑确定似乎不太正确。 Webapi 应该包含干净的函数/端点来映射来自客户端的每个请求。

【讨论】:

  • 感谢您抽出宝贵时间回复。两个 cmets -“该策略用于授权,但管理员或普通用户都可以访问控制器,它们都已获得授权”。我明白你在说什么,当加上“在我的选项中,在你的 web api 中设置两个端点/函数,一个用于管理员,一个用于用户是干净的方式”我理解你的建议是授权应该是访问端点,而不是访问数据。这回答了我的问题,并且是我的问题中提出的选项之一。
  • 我的其他评论 - “此外,您的客户端应用程序有责任确定当前用户想要返回他自己的数据或所有用户的数据。将请求发送到 web api 和让 api 通过逻辑来确定。Webapi 应该包括干净的函数/端点来映射来自客户端的每个请求。”请放心,客户端应用程序会执行此操作。但是,我认为将安全性完全放在客户端中并不是一个好的设计。提供数据访问权限的 API 应确定该请求也已获得适当授权。
  • 所以你可以尝试在web api端设置两个功能,并使用策略授权使管理员应该以管理员角色访问。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-23
  • 2018-09-16
  • 2016-06-07
  • 2017-07-04
  • 2020-08-08
  • 2011-10-24
相关资源
最近更新 更多