Asp.net core 使用IdentityServer4身份验证为ClaimsEntity设置自定义声明

Asp.net core 使用IdentityServer4身份验证为ClaimsEntity设置自定义声明,asp.net-core,identityserver4,Asp.net Core,Identityserver4,我使用IdentityServer4.TokenValidation对ASP.NET Core 2.1应用程序进行了身份验证 authenticationBuilder.AddIdentityServerAuthentication(AuthorizationConstants.IpreoAccountAuthenticationScheme,选项=> { options.RequireHttpsMetadata=false; options.ApiName=ApiName; options.A

我使用IdentityServer4.TokenValidation对ASP.NET Core 2.1应用程序进行了身份验证

authenticationBuilder.AddIdentityServerAuthentication(AuthorizationConstants.IpreoAccountAuthenticationScheme,选项=>
{
options.RequireHttpsMetadata=false;
options.ApiName=ApiName;
options.ApiSecret=ApiSecret;
选项。权限=权限;
options.legacyAudienceEvalidation=true;
});
如何将自定义声明添加到标识中的最佳方法是什么? 考虑到我们仍然需要有机会在角色验证中使用Authorize属性

例如,对于承载身份验证,我们可以使用OnTokenValidated处理程序,该处理程序在每个请求上都会被激发。但对于IdentityServerAuthenticationOptions事件,属性的类型为object,使用OnTokenValidated属性的虚拟对象初始化它不起作用

我们必须支持JWT和引用令牌。 此外,我们还需要支持多种身份验证方案


有什么想法或建议吗?

你需要中间件。作为一个例子,我建议您看看。它有同样的方法

IdentityServer处理身份验证,而授权由PolicyServer处理。在中间件中添加声明

从源代码:

///将策略服务器声明转换中间件添加到管道中。
///此中间件将应用程序角色和权限转换为声明
///并将它们添加到当前用户
公共静态IApplicationBuilder UsePolicyServerClaims(此IApplicationBuilder应用程序)
{
返回app.useMediddleware();
}
其中PolicyServerClaimsMiddleware是:

公共类PolicyServerClaimsMiddle软件
{
private readonly RequestDelegate\u next;
/// 
///初始化类的新实例。
/// 
///下一个。
public PolicyServerClaimsMiddle软件(RequestDelegate下一步)
{
_下一个=下一个;
}
/// 
///援引
/// 
///上下文。
///客户。
/// 
公共异步任务调用(HttpContext上下文,IPolicyServerRuntimeClient客户端)
{
if(context.User.Identity.IsAuthenticated)
{
var policy=await client.evaluateSync(context.User);
var roleClaims=policy.Roles.Select(x=>newclaim(“role”,x));
var permissionClaims=policy.Permissions.Select(x=>newclaims(“permission”,x));
var id=新的ClaimsEntity(“PolicyServerMiddleware”、“名称”、“角色”);
id.AddClaims(roleClaims);
id.AddClaims(许可索赔);
context.User.AddIdentity(id);
}
等待下一步(上下文);
}
}
从一开始:

public void配置服务(IServiceCollection服务)
{
services.AddMvcCore(选项=>
{
//解决方法:https://github.com/aspnet/Mvc/issues/7809
options.AllowCombiningAuthorizeFilters=false;
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddAuthorization();
//这与您无关,只是为了说明policyserver是如何实现的。
//归根结底,你可以随心所欲地实现它。
//这将设置PolicyServer客户端库和策略
//提供程序-配置从appsettings.json加载
services.AddPolicyServerClient(Configuration.GetSection(“策略”))
.addAuthorizationPermissionPolicys();
}
公共void配置(IApplicationBuilder应用程序)
{
app.UseAuthentication();
//添加此中间件以使角色和权限作为声明可用
//这主要用于使用经典的[Authorize(Roles=“foo”)]和IsInRole功能
//如果您直接使用客户端库或ASP.NET Core中新的基于策略的授权框架,则不需要这样做
app.UsePolicyServerClaims();
app.UseMvc();
}

Ruard van Elburg给了我一个使用中间件的好主意。对于多个身份验证方案,我必须更新的唯一一件事就是重写IAAuthenticationSchemeProvider以继续使用UseAuthentication中间件

因此,它根据请求内容返回默认方案

我必须做的是:

public void配置(IApplicationBuilder应用程序,IHostingEnvironment环境)
{
app.UseAuthentication();
app.useMidleware();//为经过身份验证的用户设置声明
app.UseMvc();
}
public void配置服务(IServiceCollection服务)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddTransient();
services.AddAuthorization();
services.AddAuthentication//为多个方案添加身份验证
}

必须在IdentityServer端添加声明。使用IdentityServer for auth的应用程序只能处理发送给它的内容。虽然从技术上讲,您可以通过请求的作用域在某种程度上控制索赔,但必须已设置IdentityServer,以便根据这些作用域添加某些索赔。@ChrisPratt感谢您的回答。不幸的是,我们的系统是以不同的方式设计的,来自IdentityServer的令牌在多个服务中使用,这些服务具有从多个不同地方收集的完全不同的权限/声明集。因此,我正在寻找一种方法,当身份验证通过时,如何在我的微服务中更新/添加另一个身份,而这正是我所说的不可能的。IdentityServer设置声明。您可以做的是有条件地为某些作用域设置声明,然后仅在需要这些声明的应用程序中请求这些作用域,但您不能请求未包含在某个作用域中或未包含在IdentityServer返回的默认集的一部分的特定声明。我可以覆盖IAuthorizationHandler,但在这种情况下,我必须复制许多内置逻辑(如需求验证等),我不想重复