将数据库中的用户权限存储在 JWT 令牌中的最佳实践

问题描述 投票:0回答:1

我在数据库中存储了多个权限,我在一个名为 ApiEndpoints 的表中注册了所有端点,在另一个表中, 我映射用户 ID 和端点 ID,我说它是我数据库中的权限表,它是端点和用户的桥接表,我向特定用户授予一些特定权限, 我正在使用 JWT 如何授权用户访问用户有权访问的某些 API 端点,如果有人建议这种方式而不是使用声明会更好,因为我们有一个 如果有很多端点/权限存储所有权限,那么有效负载就会过重并影响网络流量。所以我的问题是处理 JWT 令牌中的用户基础权限的最佳实践是什么?

我刚刚使用 asp.net core 6 c# 在我的 api 类型项目中实现了 JWT。

asp.net-core jwt user-permissions payload
1个回答
0
投票

我正在使用 JWT 如何授权用户访问某些 API 端点 用户有权限,如果有人建议会更好 的方式而不是使用声明,因为我们有很多 存储所有权限然后有效负载的端点/权限 太重并影响网络流量。所以我的问题是什么 处理 JWT 令牌中的用户基础权限的最佳实践?

如果您能够分享您当前的实现以寻求最佳实践或实现类型的问题,那么这总是令人期待和伟大的,这样之间就不会出现混淆或误解。

但是,根据您的描述和场景,假设您具有以下权限:

权限:

管理员:读、写、删除

编辑:读、写

观众:阅读

因此基于上述权限,我们想设置 JWT 权限。

为了在 JWT 令牌中实现上述权限,首先我们需要检查数据库中的用户权限。 因此,在数据库中,我们将检查与用户角色和指定端点关联的权限,然后执行权限和角色比较以在 JWT 中分配声明。 最后,在访问控制器时,我们将检查用户权限和凭据。

让我们看看实践中,我们如何在实践中实现这一点。

许可服务:

public class PermissionsService
{
    private readonly IUserRepository _userRepository;
    private readonly IDbContext _dbContext;

    public async Task<bool> HasPermission(string userId, string endpointId, string permission)
    {
      
        var user = await _userRepository.GetUserByIdAsync(userId);
        var userRoles = user.Roles.Select(role => role.Name).ToList(); 

       
        var allowedPermissions = await _dbContext.Permissions
            .Where(p => p.EndpointId == endpointId && userRoles.Contains(p.RoleName))
            .Select(p => p.PermissionName)
            .ToListAsync();

       
        return allowedPermissions.Contains(permission);
    }
}

注意: 在权限服务中,我正在检查用户、端点和权限,如果您只有用户和权限映射,则可以删除端点。

现在我们可以在自定义授权策略处理程序中使用上述权限服务了

授权处理程序:

public class JwtPermissionHandler : AuthorizationHandler<JwtPermissionRequirementChecker>
 {
     private readonly PermissionsService _permissionsService;

     public JwtPermissionHandler(PermissionsService permissionsService)
     {
         _permissionsService = permissionsService;
     }

     protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, JwtPermissionRequirementChecker requirement)
     {
         var userId = context.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
         if (userId != null && _permissionsService.HasPermission(userId, requirement.EndpointId, requirement.Permission))
         {
             context.Succeed(requirement);
         }
         return Task.CompletedTask;
     }
 }

权限检查器类:

public class JwtPermissionRequirementChecker : IAuthorizationRequirement
{
    public string? EndpointId { get; set; }
    public string? Permission { get; set; }
}

注册中间件:

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("EndpointPermission", policy =>
    {
        policy.Requirements.Add(new JwtPermissionRequirementChecker());
    });
});

控制器:

现在您可以在控制器操作之上使用授权过滤器。让我们看看如何做到这一点:

[Authorize(Policy = "JwtPermissionHandler", EndpointId = "SomeEndpointId", Permission = "Write")]
public IActionResult UpdateData()
{
   
}

注意:请记住,这不是您问题的确切解决方案,而是指南。因为,基于对特定角色的操作授权本身就是一个大问题。如果您有任何与此相关的其他问题,请发布新问题以及您现有的代码片段。

© www.soinside.com 2019 - 2024. All rights reserved.