Identity Server 4 向用户添加自定义声明
Identity Server 4 add custom claims to User
我已经设置了 Identity Server 4(前阵子,所以我忘记了很多事情),我正在尝试对当前登录的用户设置声明。
当我登录并使用过滤器查看他们的声明时,我可以看到:
您可以从这张图片中看到,我的范围、声明和角色已添加到用户中,这很好。
但是 claims 有一种 Role 我认为是错误的。我想将其改为 Claim:
我在我的应用程序中搜索了 ClaimTypes.Role
和 role
,但找不到我在哪里设置它。
这是可以轻松完成的事情吗?
我设法解决了这个问题;所以基本上我已经设置了角色。我只是不明白我过去是怎么做到的。要做的主要事情是设置 ApiResource,我这样做是这样的:
new ApiResource(IdentityConstants.ApiResources.IdentityServer, "Identity Server", new[] {JwtClaimTypes.Role, IdentityConstants.ClaimTypes.Permission})
我的常量class只有一些静态字符串设置如下:
public static class SituIdentityConstants
{
public static class ApiResources
{
public const string Sxp = "sxp";
public const string IdentityServer = "identity-server";
}
public static class ClaimTypes
{
public const string Permission = "permission";
}
}
完成后;我更新了我的种子并包含了这个:
private static void CreateApiResources(ConfigurationDbContext context)
{
var scopes = ListApiScopes();
var resources = ListApiResources();
foreach (var scope in scopes)
if (!context.ApiScopes.Any(m => m.Name.Equals(scope.Name)))
context.ApiScopes.Add(scope.ToEntity());
foreach (var resource in resources)
{
if (context.ApiResources.Any(m => m.Name.Equals(resource.Name))) continue;
var entity = resource.ToEntity();
entity.Scopes = scopes.Select(m => new ApiResourceScope
{
Scope = m.Name
}).ToList();
context.Add(entity);
}
context.SaveChanges();
}
它创建了所有 API 资源、范围和任何 ApiResourceClaims(这是在 IProfileService
.
中填充 RequestedClaimTypes
的内容
顺便说一句,作为参考,这是我的 ProfileService:
public class ProfileService: IProfileService
{
private readonly IMediator _mediator;
private readonly UserManager<User> _userManager;
private readonly RoleManager<Role> _roleManager;
public ProfileService(IMediator mediator, UserManager<User> userManager, RoleManager<Role> roleManager)
{
_mediator = mediator;
_userManager = userManager;
_roleManager = roleManager;
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var user = await _userManager.FindByIdAsync(context.Subject.GetSubjectId());
var rolesAttempt = await _mediator.Send(new ListRoles());
if (rolesAttempt.Failure) return;
var roles = rolesAttempt.Result;
var issuedClaims = new List<System.Security.Claims.Claim>();
foreach (var role in roles)
{
if (!user.Roles.Any(m => m.RoleId.Equals(role.Id))) continue;
issuedClaims.Add(new System.Security.Claims.Claim(JwtClaimTypes.Role, role.Name));
var roleClaims = await _roleManager.GetClaimsAsync(new Role {Id = role.Id});
issuedClaims.AddRange(roleClaims.Where(m => context.RequestedClaimTypes.Any(x => x.Equals(m.Type))));
}
context.IssuedClaims = issuedClaims;
}
public async Task IsActiveAsync(IsActiveContext context)
{
var sub = context.Subject.GetSubjectId();
var user = await _userManager.FindByIdAsync(sub);
var active = (user != null && (!user.LockoutEnabled || user.LockoutEnd == null)) ||
(user != null && user.LockoutEnabled && user.LockoutEnd != null &&
DateTime.UtcNow > user.LockoutEnd);
context.IsActive = active;
}
}
我实际上发现设置起来很痛苦。我尝试了文档说明的方式:
services.AddIdentityServer()
.AddDeveloperSigningCredential()
// Stores clients and resources
.AddConfigurationStore(options => options.ConfigureDbContext = ConfigureDbContext)
// Stores tokens, consents, codes, etc
.AddOperationalStore(options => options.ConfigureDbContext = ConfigureDbContext)
.AddProfileService<ProfileService>()
.AddAspNetIdentity<User>();
但这对我不起作用;所以我这样做了:
services.AddIdentityServer()
.AddDeveloperSigningCredential()
// Stores clients and resources
.AddConfigurationStore(options => options.ConfigureDbContext = ConfigureDbContext)
// Stores tokens, consents, codes, etc
.AddOperationalStore(options => options.ConfigureDbContext = ConfigureDbContext)
.AddAspNetIdentity<User>();
services.AddScoped(typeof(IProfileService), typeof(ProfileService));
这就是我需要为 Identity Server 做的所有事情,RequestedClaimTypes
现在填充了“角色”和“权限”。我唯一做的另一件事是,当我创建一个 RoleClaim 时,我将声明类型设置为“许可”并且它有效:
{
"nbf": 1611600995,
"exp": 1611604595,
"iss": "https://localhost:44362",
"aud": [
"sxp",
"identity-server"
],
"client_id": "client",
"sub": "949cc454-d7c9-45db-9eae-59e72d3025c1",
"auth_time": 1611600983,
"idp": "local",
"role": "User Manager",
"permission": [
"users:write",
"user:read"
],
"jti": "39C9F31958972704730DA65A8FCDAAEE",
"iat": 1611600995,
"scope": [
"identity:read",
"identity:write",
"sxp:read",
"sxp:write"
],
"amr": [
"pwd"
]
}
噪音。
我已经设置了 Identity Server 4(前阵子,所以我忘记了很多事情),我正在尝试对当前登录的用户设置声明。 当我登录并使用过滤器查看他们的声明时,我可以看到:
您可以从这张图片中看到,我的范围、声明和角色已添加到用户中,这很好。 但是 claims 有一种 Role 我认为是错误的。我想将其改为 Claim:
我在我的应用程序中搜索了 ClaimTypes.Role
和 role
,但找不到我在哪里设置它。
这是可以轻松完成的事情吗?
我设法解决了这个问题;所以基本上我已经设置了角色。我只是不明白我过去是怎么做到的。要做的主要事情是设置 ApiResource,我这样做是这样的:
new ApiResource(IdentityConstants.ApiResources.IdentityServer, "Identity Server", new[] {JwtClaimTypes.Role, IdentityConstants.ClaimTypes.Permission})
我的常量class只有一些静态字符串设置如下:
public static class SituIdentityConstants
{
public static class ApiResources
{
public const string Sxp = "sxp";
public const string IdentityServer = "identity-server";
}
public static class ClaimTypes
{
public const string Permission = "permission";
}
}
完成后;我更新了我的种子并包含了这个:
private static void CreateApiResources(ConfigurationDbContext context)
{
var scopes = ListApiScopes();
var resources = ListApiResources();
foreach (var scope in scopes)
if (!context.ApiScopes.Any(m => m.Name.Equals(scope.Name)))
context.ApiScopes.Add(scope.ToEntity());
foreach (var resource in resources)
{
if (context.ApiResources.Any(m => m.Name.Equals(resource.Name))) continue;
var entity = resource.ToEntity();
entity.Scopes = scopes.Select(m => new ApiResourceScope
{
Scope = m.Name
}).ToList();
context.Add(entity);
}
context.SaveChanges();
}
它创建了所有 API 资源、范围和任何 ApiResourceClaims(这是在 IProfileService
.
RequestedClaimTypes
的内容
顺便说一句,作为参考,这是我的 ProfileService:
public class ProfileService: IProfileService
{
private readonly IMediator _mediator;
private readonly UserManager<User> _userManager;
private readonly RoleManager<Role> _roleManager;
public ProfileService(IMediator mediator, UserManager<User> userManager, RoleManager<Role> roleManager)
{
_mediator = mediator;
_userManager = userManager;
_roleManager = roleManager;
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var user = await _userManager.FindByIdAsync(context.Subject.GetSubjectId());
var rolesAttempt = await _mediator.Send(new ListRoles());
if (rolesAttempt.Failure) return;
var roles = rolesAttempt.Result;
var issuedClaims = new List<System.Security.Claims.Claim>();
foreach (var role in roles)
{
if (!user.Roles.Any(m => m.RoleId.Equals(role.Id))) continue;
issuedClaims.Add(new System.Security.Claims.Claim(JwtClaimTypes.Role, role.Name));
var roleClaims = await _roleManager.GetClaimsAsync(new Role {Id = role.Id});
issuedClaims.AddRange(roleClaims.Where(m => context.RequestedClaimTypes.Any(x => x.Equals(m.Type))));
}
context.IssuedClaims = issuedClaims;
}
public async Task IsActiveAsync(IsActiveContext context)
{
var sub = context.Subject.GetSubjectId();
var user = await _userManager.FindByIdAsync(sub);
var active = (user != null && (!user.LockoutEnabled || user.LockoutEnd == null)) ||
(user != null && user.LockoutEnabled && user.LockoutEnd != null &&
DateTime.UtcNow > user.LockoutEnd);
context.IsActive = active;
}
}
我实际上发现设置起来很痛苦。我尝试了文档说明的方式:
services.AddIdentityServer()
.AddDeveloperSigningCredential()
// Stores clients and resources
.AddConfigurationStore(options => options.ConfigureDbContext = ConfigureDbContext)
// Stores tokens, consents, codes, etc
.AddOperationalStore(options => options.ConfigureDbContext = ConfigureDbContext)
.AddProfileService<ProfileService>()
.AddAspNetIdentity<User>();
但这对我不起作用;所以我这样做了:
services.AddIdentityServer()
.AddDeveloperSigningCredential()
// Stores clients and resources
.AddConfigurationStore(options => options.ConfigureDbContext = ConfigureDbContext)
// Stores tokens, consents, codes, etc
.AddOperationalStore(options => options.ConfigureDbContext = ConfigureDbContext)
.AddAspNetIdentity<User>();
services.AddScoped(typeof(IProfileService), typeof(ProfileService));
这就是我需要为 Identity Server 做的所有事情,RequestedClaimTypes
现在填充了“角色”和“权限”。我唯一做的另一件事是,当我创建一个 RoleClaim 时,我将声明类型设置为“许可”并且它有效:
{
"nbf": 1611600995,
"exp": 1611604595,
"iss": "https://localhost:44362",
"aud": [
"sxp",
"identity-server"
],
"client_id": "client",
"sub": "949cc454-d7c9-45db-9eae-59e72d3025c1",
"auth_time": 1611600983,
"idp": "local",
"role": "User Manager",
"permission": [
"users:write",
"user:read"
],
"jti": "39C9F31958972704730DA65A8FCDAAEE",
"iat": 1611600995,
"scope": [
"identity:read",
"identity:write",
"sxp:read",
"sxp:write"
],
"amr": [
"pwd"
]
}
噪音。