【问题标题】:How to handle requirements based resource authorization when there are many resource permissions with respect to performance?当有许多关于性能的资源权限时,如何处理基于需求的资源授权?
【发布时间】:2021-09-29 02:41:22
【问题描述】:

我有一个使用基于 JWT 的身份验证的 Web 服务。在一些示例中,我看到权限被添加到声明标识中,然后在 AuthorizationHandler 中查询。

这也是生产级解决方案的方式吗?由于权限是在 JWT 令牌中编码的,因此我担心拥有非常大的 JWT 令牌对性能的影响。

鉴于在某些时候您可能会得到 1mb+ 及以上的 JWT 令牌,如果 Web api 客户端的上传速度不足,这可能会导致性能非常差。

是否有处理大量权限的最佳做法? (目前我认为要走的路可能是做缓存的数据库查询来访问权限授予)

【问题讨论】:

    标签: asp.net-core jwt


    【解决方案1】:

    您已经注意到,将过多的声明放入 JWT 会带来问题。如果标头超过一定大小,某些服务器将停止解析标头。在我们的测试中,IIS 在约 150 个范围声明(约 2KB 的 JWT)后停止接受请求,因此您没有太多空间可以使用。

    您应该将 JWT 的使用限制为身份验证。如果应用程序有权访问授权数据,您可以使用令牌从数据库或某些授权/策略服务中获取该用户的权限声明。

    ASP.NET Core 为这些场景提供了一个接口。如果你实现 IClaimsTransformation 并注册它,ASP.NET Core will call it when it authenticates the user。然后,您将有机会使用用户的授权声明填充 ClaimsPrincipal

    您需要注意的一件事是,每次进行身份验证时都会调用它,因此您需要检查您是否已经填充了声明以防止重复声明。如果操作正确,则需要对每个请求执行一次查询,以获取用户的授权声明。

    一个示例实现:

    public class LoadUserClaimsTransformer : IClaimsTransformation
    {
        private AppDbContext _db;
    
        public LoadUserClaimsTransformer(AppDbContext db)
        {
            _db = db;
        }
    
        public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
        {
            // check if we've already populated the claims
            if (principal.HasClaim(c => c.Type == "permission"))
            {
                return principal;
            }
    
            if (principal.Identity is ClaimsIdentity identity)
            {
                var userId = principal.FindFirstValue(ClaimTypes.NameIdentifier);
                var permissions = await _db.Set<Permission>().Where(it => it.UserId == userId).ToListAsync();
                foreach (var permission in permissions)
                {
                    identity.AddClaim(new Claim("permission", permission.Key));
                }
            }
    
            return principal;
        }
    }
    
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<IClaimsTransformation, LoadUserClaimsTransformer>();
        // ...
    }
    

    将声明添加到 ClaimsPrincipal 后,您可以使用 [Authorize] 注释进行声明性检查,或使用 IAuthorizationService 进行命令式检查或基于资源的授权。

    资源:

    【讨论】:

      猜你喜欢
      • 2023-03-25
      • 2013-09-22
      • 2021-08-31
      • 2019-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-12
      • 2015-03-23
      相关资源
      最近更新 更多