ASP.NET 核心 Web API:基于数据库权限的授权

El *_*ppo 6 c# asp.net-core-webapi

我正在寻找一种解决方案/建议来帮助我创建基于权限的对 web api 端点/控制器操作的访问。

基于角色的访问不合适,因为我没有可以在 Role("Admin") 或 Role("Controller") 之类的代码中使用的固定规则。

基于声明的权限也不可行,因为每个用户/客户可以对每个业务对象/实体拥有不同的权限(例如,对自己的工单的读/写访问权限和对他/她公司的所有工单的读访问权限,或者如果它是我的技术人员)公司完全访问所有客户的所有票证。因此,每个用户将有 10 条甚至 10 条索赔要求,我必须在每次访问我的 API 时对其进行评估。

它是数据库中的某种多租户,租户是我们的客户,拥有某种可以访问所有租户数据的“主租户”。

我认为像 Visual Guard 这样的东西可以满足我的需求,但它非常昂贵,而且他们现在不支持网络核心,而且他们的文档似乎已经过时了。

我不需要立即提供一个可用的解决方案,但是一些提示和技巧如何实现这一点将非常受欢迎,因为我现在正在寻找和搜索一段时间。

“数据库权限”的详细信息: 我的意思是在我的前端(Winforms 应用程序)中我想建立一个安全系统,我可以在其中为用户创建和分配角色,并在这些角色中定义用户可以执行哪些操作以及哪些 CRUD 操作他/她可以处理特定的业务对象。每个角色可以有 n 个用户,每个角色可以有 n 个权限。对自身的每个权限声明为例如 Create:false、Read:true、Write:true 和 Delete:false。如果未找到特定业务对象的权限,则该 BO 上的 CRUD 将被完全拒绝。

因此,每当我的 API 中的某个操作被调用时,我都必须检查该用户及其规则是否允许他根据我的数据库中的规则和权限执行该特定操作。

详细说明应用程序结构: 前端将是一个 Winforms 应用程序,它通过 OData 在后台调用 API。我不想仅仅依赖 Winforms 应用程序中的安全性,因为可以从 Internet 访问该 API,而且我无法确定用户是否不会尝试使用他的凭据访问 api 只是为了看看什么是 possblie 没有“前端过滤器”。因此权限位于 API 中,如果用户尝试访问前端应用程序中的 st,应用程序本身会“询问”API 是否可能。稍后我想创建也使用 Odata Web API 的移动客户端。

Lie*_*ero 5

ASP.NET Core中相关的API有:

  • 授权服务
  • 授权策略
  • I授权要求
  • IAuthorizationHandler

您正在寻找的授权模式称为基于资源的授权

https://learn.microsoft.com/en-us/aspnet/core/security/authorization/resourcebased?view=aspnetcore-2.2

基本上,您可以定义 AuthorizationPolicy,并将其应用到资源实例:

var ticket = _ticketRepository.Find(ticketID);

var authorizationResult = await _authorizationService
        .AuthorizeAsync(User, ticket, "EditTicketPolicy");
Run Code Online (Sandbox Code Playgroud)

在授权处理程序中,您可以检查用户是否是资源的所有者。

public class ResourceOwnerRequirement : IAuthorizationRequirement
{
}

public class ResourceOwnerHandler 
    : AuthorizationHandler<ResourceOwnerRequirement, MyBusinessObject>
    //: AuthorizationHandler<ResourceOwnerRequirement> use this overload to handle all types of resources...
{
    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context, 
        ResourceOwnerRequirement requirement, 
        MyBusinessObject resource)
    {
        int createdByUserId = resource.CreatedBy;
        Claim userIdClaim = ((ClaimsIdentity)context.User.Identity).FindFirst("UserId");

        if (int.TryParse(userIdClaim.Value, out int userId)
            && createdByUserId == userId)
        {
            context.Succeed(requirement);
        }
    }
}

//admin can do anything
public class AdminRequirementHandler : IAuthorizationHandler
{
    public Task HandleAsync(AuthorizationHandlerContext context)
    {
        if (context.User.Claims.Any(c => c.Type == "Role" && c.Value == "Administator"))
        {
            while (context.PendingRequirements.Any())
            {
                context.Succeed(context.PendingRequirements.First());
            }
        }
        return Task.CompletedTask;
    }
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,这仍然可以称为声明或基于角色的授权。具有特定角色的用户可以编辑自己的工单,但具有管理员角色的用户也可以编辑其他工单。区别在于您对资源应用授权,而不仅仅是操作

编辑: