我在数据库中存储了多个权限,我在一个名为 ApiEndpoints 的表中注册了所有端点,在另一个表中, 我映射用户 ID 和端点 ID,我说它是我数据库中的权限表,它是端点和用户的桥接表,我向特定用户授予一些特定权限, 我正在使用 JWT 如何授权用户访问用户有权访问的某些 API 端点,如果有人建议这种方式而不是使用声明会更好,因为我们有一个 如果有很多端点/权限存储所有权限,那么有效负载就会过重并影响网络流量。所以我的问题是处理 JWT 令牌中的用户基础权限的最佳实践是什么?
我刚刚使用 asp.net core 6 c# 在我的 api 类型项目中实现了 JWT。
我正在使用 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()
{
}
注意:请记住,这不是您问题的确切解决方案,而是指南。因为,基于对特定角色的操作授权本身就是一个大问题。如果您有任何与此相关的其他问题,请发布新问题以及您现有的代码片段。