所以,经过调查,我想出了两种方法来做到这一点:
- 在身份服务器端包含角色/其他声明
- 在客户端包含角色/其他声明
包含在身份服务器端
ravi punjwani 在“如何使用带有 IdentityServer4 的 ASP.Net Identity 添加附加声明以包含在 access_token 中”中提供了答案。他的解决方案仍处于草稿阶段,但该解决方案允许您在将令牌发送回客户端之前添加任何声明。这是链接:How to add additional claims to be included in the access_token using ASP.Net Identity with IdentityServer4
包含在客户端
这个有点难,因为它涉及在客户端的请求管道中添加“IClaimsTransformer”。结果是,对于每个请求,Claimstransformer 将检索用户的声明并将其添加到用户身份声明(令牌)中。 Claimstransformer 的设置并不容易,因为让 DI 工作很棘手,但经过大量研究后,celow 解决方案为我做到了。
Custom ClaimsTransformer 类在中间件中进行转换:
公共类 KarekeClaimsTransformer : IClaimsTransformer
{
私有只读 UserManager _userManager;
public KarekeClaimsTransformer(UserManager<ApplicationUser> userManager)
{
_userManager = userManager;
}
public async Task<ClaimsPrincipal> TransformAsync(ClaimsTransformationContext context)
{
if (context.Principal.Identity.IsAuthenticated)
{
Claim userId = context.Principal.FindFirst("sub");
if (context.Principal.FindFirst("role") == null && userId != null)
{
ApplicationUser user = await _userManager.FindByIdAsync(userId.Value);
var roles = await _userManager.GetRolesAsync(user);
foreach (var role in roles)
{
((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim(JwtClaimTypes.Role, role,
"http://schemas.microsoft.com/ws/2008/06/identity/claims/role"));
}
}
}
return Task.FromResult(context.Principal).Result;
}
}
在Client启动类中需要添加到ConfigureServices中的作用域
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
...
services.AddScoped<IClaimsTransformer, KarekeClaimsTransformer>();
// Add framework services.
services.AddMvc();
}
最后,添加配置:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
{
Authority = "http://localhost:5000",
RequireHttpsMetadata = false,
ApiName = "api1"
});
app.UseClaimsTransformation((context) =>
{
IClaimsTransformer transformer = context.Context.RequestServices.GetRequiredService<IClaimsTransformer>();
return transformer.TransformAsync(context);
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "api/{controller}/{action?}/{id?}");
});
}