如何在 ASP.net 核心身份中实现基于权限的授权?
How to implement permission based authorization in ASP.net core Identity?
我正在尝试使用 asp.net Identity Core 保护我的 webAPI。现在我想动态创建角色并在我的管理面板中设置和删除权限 from/to。
例如,我有这个权限列表:
- 注册任务
- 分配任务
- 更改任务状态
- 验证任务状态
现在我想创建不同的角色并根据需要为它们设置此权限,并将这些角色分配给每个用户。
我在Identity framework的UserManager和RoleManager中搜索,但没有办法创建这个功能。
有什么方法可以实现这个功能吗?
我发现 this 很有用,但这是关于 dotnet
我在 this link 中找到了一种使用声明和策略创建基于权限的授权的方法。
我创建了一个自定义声明类型,例如 Application.Permission,然后创建了一些 类 来定义我的权限:
public class CustomClaimTypes
{
public const string Permission = "Application.Permission";
}
public static class UserPermissions
{
public const string Add = "users.add";
public const string Edit = "users.edit";
public const string EditRole = "users.edit.role";
}
然后我创建我的角色,然后将这些权限作为声明分配给具有键 ApplicationPermission.
的角色
await roleManager.CreateAsync(new ApplicationRole("User"));
var userRole = await roleManager.FindByNameAsync("User");
await roleManager.AddClaimAsync(userRole, new Claim(CustomClaimTypes.Permission, Permissions.User.View));
await roleManager.AddClaimAsync(userRole, new Claim(CustomClaimTypes.Permission, Permissions.Team.View));
在下一步中,当用户尝试登录系统时,我将这些声明添加到我的令牌中:
var roles = await _userManager.GetRolesAsync(user);
var userRoles = roles.Select(r => new Claim(ClaimTypes.Role, r)).ToArray();
var userClaims = await _userManager.GetClaimsAsync(user).ConfigureAwait(false);
var roleClaims = await GetRoleClaimsAsync(roles).ConfigureAwait(false);
var claims = new[]
{
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
new Claim(ClaimTypes.Email, user.Email),
new Claim(ClaimTypes.Name, user.UserName)
}.Union(userClaims).Union(roleClaims).Union(userRoles);
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSettings.SigningKey));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: _jwtSettings.Issuer,
audience: _jwtSettings.Audience,
claims: claims,
expires: DateTime.UtcNow.AddYears(1),
signingCredentials: creds);
然后我以这种方式创建我的策略:
public static class PolicyTypes
{
public static class Users
{
public const string Manage = "users.manage.policy";
public const string EditRole = "users.edit.role.policy";
}
}
然后我在 ConfigureServiceSection 的 startup.cs 文件中设置我的授权服务:
services.AddAuthorization(options =>
{
options.AddPolicy(PolicyTypes.Users.Manage, policy => { policy.RequireClaim(CustomClaimTypes.Permission, Permissions.Users.Add); });
options.AddPolicy(PolicyTypes.Users.EditRole, policy => { policy.RequireClaim(CustomClaimTypes.Permission, Permissions.Users.EditRole); });
}
最后,我在路线上设置策略并完成:
[Authorize(Policy = PolicyTypes.Users.Manage)]
public async Task<IEnumerable<TeamDto>> GetSubTeams(int parentId)
{
var teams = await _teamService.GetSubTeamsAsync(parentId);
return teams;
}
另一种解决方案可能是使用 funcs 来完成策略,请参阅此示例取自 https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-3.1:
services.AddAuthorization(options =>
{
options.AddPolicy("BadgeEntry", policy =>
policy.RequireAssertion(context =>
context.User.HasClaim(c =>
(c.Type == "BadgeId" ||
c.Type == "TemporaryBadgeId") &&
c.Issuer == "https://microsoftsecurity")));
});
考虑到这一点,您可以制作如下内容。
首先 class 您的所有个人权限:
public static class PrincipalPermission{
public static List<Func<AuthorizationHandlerContext, bool>> Criteria = new List<Func<AuthorizationHandlerContext, bool>>
{
CanCreateUser
};
public static bool CanCreateUser(this AuthorizationHandlerContext ctx)
{
return ctx.User.IsInRole(RoleEnum.Admin.ToString());
}
}
那么这应该添加到您的配置中:
services.AddAuthorization(options =>
{
foreach (var criterion in PrincipalPermissions.Criteria)
{
options.AddPolicy(criterion.Method.Name,
policy => policy.RequireAssertion(criterion));
}
}
现在可以将其添加到您的控制器中:
[Authorize(Policy = nameof(PrincipalPermissions.CanCreateUser))]
public async Task<UserDto> Create([FromBody] CreateUserCommand cmd)
{
return await HandleCreateUser(cmd);
}
顺便说一句,如果有人认为将这些方法添加到 Criteria
列表很烦人,我就在你身边,如果有人能提出更好的解决方案,我将不胜感激 :)
我正在尝试使用 asp.net Identity Core 保护我的 webAPI。现在我想动态创建角色并在我的管理面板中设置和删除权限 from/to。
例如,我有这个权限列表:
- 注册任务
- 分配任务
- 更改任务状态
- 验证任务状态
现在我想创建不同的角色并根据需要为它们设置此权限,并将这些角色分配给每个用户。
我在Identity framework的UserManager和RoleManager中搜索,但没有办法创建这个功能。
有什么方法可以实现这个功能吗? 我发现 this 很有用,但这是关于 dotnet
我在 this link 中找到了一种使用声明和策略创建基于权限的授权的方法。
我创建了一个自定义声明类型,例如 Application.Permission,然后创建了一些 类 来定义我的权限:
public class CustomClaimTypes
{
public const string Permission = "Application.Permission";
}
public static class UserPermissions
{
public const string Add = "users.add";
public const string Edit = "users.edit";
public const string EditRole = "users.edit.role";
}
然后我创建我的角色,然后将这些权限作为声明分配给具有键 ApplicationPermission.
的角色await roleManager.CreateAsync(new ApplicationRole("User"));
var userRole = await roleManager.FindByNameAsync("User");
await roleManager.AddClaimAsync(userRole, new Claim(CustomClaimTypes.Permission, Permissions.User.View));
await roleManager.AddClaimAsync(userRole, new Claim(CustomClaimTypes.Permission, Permissions.Team.View));
在下一步中,当用户尝试登录系统时,我将这些声明添加到我的令牌中:
var roles = await _userManager.GetRolesAsync(user);
var userRoles = roles.Select(r => new Claim(ClaimTypes.Role, r)).ToArray();
var userClaims = await _userManager.GetClaimsAsync(user).ConfigureAwait(false);
var roleClaims = await GetRoleClaimsAsync(roles).ConfigureAwait(false);
var claims = new[]
{
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
new Claim(ClaimTypes.Email, user.Email),
new Claim(ClaimTypes.Name, user.UserName)
}.Union(userClaims).Union(roleClaims).Union(userRoles);
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSettings.SigningKey));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: _jwtSettings.Issuer,
audience: _jwtSettings.Audience,
claims: claims,
expires: DateTime.UtcNow.AddYears(1),
signingCredentials: creds);
然后我以这种方式创建我的策略:
public static class PolicyTypes
{
public static class Users
{
public const string Manage = "users.manage.policy";
public const string EditRole = "users.edit.role.policy";
}
}
然后我在 ConfigureServiceSection 的 startup.cs 文件中设置我的授权服务:
services.AddAuthorization(options =>
{
options.AddPolicy(PolicyTypes.Users.Manage, policy => { policy.RequireClaim(CustomClaimTypes.Permission, Permissions.Users.Add); });
options.AddPolicy(PolicyTypes.Users.EditRole, policy => { policy.RequireClaim(CustomClaimTypes.Permission, Permissions.Users.EditRole); });
}
最后,我在路线上设置策略并完成:
[Authorize(Policy = PolicyTypes.Users.Manage)]
public async Task<IEnumerable<TeamDto>> GetSubTeams(int parentId)
{
var teams = await _teamService.GetSubTeamsAsync(parentId);
return teams;
}
另一种解决方案可能是使用 funcs 来完成策略,请参阅此示例取自 https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-3.1:
services.AddAuthorization(options =>
{
options.AddPolicy("BadgeEntry", policy =>
policy.RequireAssertion(context =>
context.User.HasClaim(c =>
(c.Type == "BadgeId" ||
c.Type == "TemporaryBadgeId") &&
c.Issuer == "https://microsoftsecurity")));
});
考虑到这一点,您可以制作如下内容。
首先 class 您的所有个人权限:
public static class PrincipalPermission{
public static List<Func<AuthorizationHandlerContext, bool>> Criteria = new List<Func<AuthorizationHandlerContext, bool>>
{
CanCreateUser
};
public static bool CanCreateUser(this AuthorizationHandlerContext ctx)
{
return ctx.User.IsInRole(RoleEnum.Admin.ToString());
}
}
那么这应该添加到您的配置中:
services.AddAuthorization(options =>
{
foreach (var criterion in PrincipalPermissions.Criteria)
{
options.AddPolicy(criterion.Method.Name,
policy => policy.RequireAssertion(criterion));
}
}
现在可以将其添加到您的控制器中:
[Authorize(Policy = nameof(PrincipalPermissions.CanCreateUser))]
public async Task<UserDto> Create([FromBody] CreateUserCommand cmd)
{
return await HandleCreateUser(cmd);
}
顺便说一句,如果有人认为将这些方法添加到 Criteria
列表很烦人,我就在你身边,如果有人能提出更好的解决方案,我将不胜感激 :)