Authentication MVC核心Web API中的自定义JWT令牌授权
我一直在实现我自己的JWT令牌Authentication MVC核心Web API中的自定义JWT令牌授权,authentication,asp.net-core,asp.net-core-middleware,Authentication,Asp.net Core,Asp.net Core Middleware,我一直在实现我自己的JWT令牌身份验证/授权,而没有使用身份等 基于这些链接,我成功创建了JWT令牌,并使用属性[Authorize] -[我的代码与此完全相同] 我遇到的问题是,在我正在处理的应用程序中,授权基于功能而不是角色 这是数据库模式 1. User ------------------- UserId (PK) 2. Role ------------------- RoleId (PK) 3. RoleFeatures -------------------
身份验证/授权
,而没有使用身份等
基于这些链接,我成功创建了JWT令牌,并使用属性[Authorize]
-[我的代码与此完全相同]
我遇到的问题是,在我正在处理的应用程序中,授权基于功能
而不是角色
这是数据库模式
1. User
-------------------
UserId (PK)
2. Role
-------------------
RoleId (PK)
3. RoleFeatures
-------------------
(RoleId PK, FK)
(FeatureId PK, FK)
4. Features
-------------------
FeatureId (PK)
角色不是预定义的,但功能是预定义的,例如创建用户、更新用户
假设我们有两个角色“用户管理员”
和“用户和客户管理员”
-这两个角色的用户都可以创建、更新和删除用户
现在在应用程序控制器中,而不是执行
[Authorise(Roles="User Manager, User and Customer Admin")]
public IActionResult CreateUser()
我需要这个:
[Authorise(Features="Create User")]
public IActionResult CreateUser()
如何在MVC核心Web API中实现这种类型的JWT令牌授权
一种方法是将JWT令牌中的特性保存为声明,但问题是角色可以有20个特性,而将它们保存在令牌中会显著增加令牌的大小-
因此,我需要的是Authorize属性的自定义实现,它从JWT令牌中获取用户ID(用户ID是JWT令牌中的声明),然后根据用户ID从DB中获取角色特性并应用授权
编辑
基于.NET核心文档,我发现我可以创建一个策略
因此,我继续创建了一个需求和一个需求处理程序,如下所示:
public class FeatureRequirement : IAuthorizationRequirement
{
public string FeatureName { get; set; }
public FeatureRequirement(string featureName) { FeatureName = featureName; }
}
public class FeatureRequirementHandler : AuthorizationHandler<FeatureRequirement>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FeatureRequirement requirement)
{
var userId = context.User.Claims.FirstOrDefault(s => s.Type == "UserId");
if (userId == null) { return Task.FromResult(0); }
//TODO: Get User Features from DB based on UserId
var userFeatures = new List<string> { "Create User", "Update User" };
if (userFeatures.Contains(requirement.FeatureName))
{
context.Succeed(requirement);
}
return Task.FromResult(0);
}
}
按预期工作(如果未将功能分配给用户,则返回403)
问题是,我必须为每项功能创建一个新的策略-有更好的方法吗?请参见,尤其是阅读评论。@ademcaglin似乎我的编辑才是正确的选择?必须使用循环在Startup.cs中注册多个策略…请参阅,尤其是阅读注释。@ademcaglin看来我的编辑是正确的选择?必须使用循环在Startup.cs中注册多个策略。。。
services.AddAuthorization(options =>
{
// Create the Policies
// Problem here have to define a policy for each feature
options.AddPolicy("Create User", policy => policy.Requirements.Add(new FeatureRequirement("Create User")));
options.AddPolicy("Update User", policy => policy.Requirements.Add(new FeatureRequirement("Update User")));
});
services.AddScoped<IAuthorizationHandler, FeatureRequirementHandler>();
[Authorise(Policy="Create User")]
public IActionResult CreateUser()
// AND
[Authorise(Policy="Update User")]
public IActionResult UpdateUser()