我有一个使用IdentityServer4.TokenValidation进行身份验证的ASP.NET Core 2.1应用程序
authenticationBuilder.AddIdentityServerAuthentication(AuthorizationConstants.IpreoAccountAuthenticationScheme, options =>
{
options.RequireHttpsMetadata = false;
options.ApiName = apiName;
options.ApiSecret = apiSecret;
options.Authority = authority;
options.LegacyAudienceValidation = true;
});
如何向身份添加自定义声明的最佳方法是什么?考虑到我们仍然需要有机会使用带有角色验证的Authorize属性。
例如,对于承载认证,我们可以使用OnTokenValidated处理程序,该处理程序在每个请求上触发。但是对于IdentityServerAuthenticationOptions事件属性是对象类型,并使用具有OnTokenValidated属性的虚拟对象初始化它不起作用。
我们必须支持JWT和参考令牌。我们还需要支持多种身份验证方案
任何想法或建议?
Ruard van Elburg给了我一个关于使用中间件的好主意。我唯一需要更新的方法是使用这种方法进行多种身份验证方案,重写IAuthenticationSchemeProvider以继续使用UseAuthentication中间件。
因此它根据请求内容返回默认方案
我必须做的事情:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
app.UseMiddleware<ClaimsMiddleware>(); // to set claims for authenticated user
app.UseMvc();
}
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddTransient<IAuthenticationSchemeProvider, CustomAuthenticationSchemeProvider>();
services.AddAuthorization();
services.AddAuthentication // add authentication for multiple schemes
}
你需要中间件。作为一个例子,我建议你看看PolicyServer。它有相同的方法。
IdentityServer处理身份验证,而授权由PolicyServer处理。 free OSS version在中间件中添加了声明。
从源代码:
/// Add the policy server claims transformation middleware to the pipeline.
/// This middleware will turn application roles and permissions into claims
/// and add them to the current user
public static IApplicationBuilder UsePolicyServerClaims(this IApplicationBuilder app)
{
return app.UseMiddleware<PolicyServerClaimsMiddleware>();
}
PolicyServerClaimsMiddleware的位置是:
public class PolicyServerClaimsMiddleware
{
private readonly RequestDelegate _next;
/// <summary>
/// Initializes a new instance of the <see cref="PolicyServerClaimsMiddleware"/> class.
/// </summary>
/// <param name="next">The next.</param>
public PolicyServerClaimsMiddleware(RequestDelegate next)
{
_next = next;
}
/// <summary>
/// Invoke
/// </summary>
/// <param name="context">The context.</param>
/// <param name="client">The client.</param>
/// <returns></returns>
public async Task Invoke(HttpContext context, IPolicyServerRuntimeClient client)
{
if (context.User.Identity.IsAuthenticated)
{
var policy = await client.EvaluateAsync(context.User);
var roleClaims = policy.Roles.Select(x => new Claim("role", x));
var permissionClaims = policy.Permissions.Select(x => new Claim("permission", x));
var id = new ClaimsIdentity("PolicyServerMiddleware", "name", "role");
id.AddClaims(roleClaims);
id.AddClaims(permissionClaims);
context.User.AddIdentity(id);
}
await _next(context);
}
}
从创业公司:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore(options =>
{
// workaround: https://github.com/aspnet/Mvc/issues/7809
options.AllowCombiningAuthorizeFilters = false;
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddAuthorization();
// This is not relevant for you, but just to show how policyserver is implemented.
// The bottom line is that you can implement this anyway you like.
// this sets up the PolicyServer client library and policy
// provider - configuration is loaded from appsettings.json
services.AddPolicyServerClient(Configuration.GetSection("Policy"))
.AddAuthorizationPermissionPolicies();
}
public void Configure(IApplicationBuilder app)
{
app.UseAuthentication();
// add this middleware to make roles and permissions available as claims
// this is mainly useful for using the classic [Authorize(Roles="foo")] and IsInRole functionality
// this is not needed if you use the client library directly or the new policy-based authorization framework in ASP.NET Core
app.UsePolicyServerClaims();
app.UseMvc();
}