多种身份验证方案,包括客户端证书和身份用户
Multiple Authentication Scheme including Client Certificate and Identity User
完成客户端证书 X.509 身份验证后,如何根据数据库中的 AspNetUsers table 对客户端证书 ID 进行身份验证。
如果我将 SignInManager 与 OnValidateCertificate 放在一起,它会在每次请求时被调用,并且 SignInManager 会在每次请求时签署用户。
请告知如何仅调用一次 SignInManager 以使用 AspNetUsers 进行身份验证。
请注意,客户端证书 ID 在 AspNetUsers 中存储为用户名。
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<ApplicationUser>()
.AddRoles<IdentityRole>()
.AddDefaultUI(UIFramework.Bootstrap4)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(options =>
{
options.Events = new CertificateAuthenticationEvents
{
OnValidateCertificate = context =>
{
var claims = new[]
{
new Claim(ClaimTypes.NameIdentifier, context.ClientCertificate.Subject, ClaimValueTypes.String, context.Options.ClaimsIssuer),
new Claim(ClaimTypes.Name, context.ClientCertificate.Subject, ClaimValueTypes.String, context.Options.ClaimsIssuer)
};
context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims, context.Scheme.Name));
context.Success();
return Task.CompletedTask;
}
};
});
services.AddMvc(config =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
});
}
根据下面 Barry Dorrans 的回复 URL
https://github.com/blowdart/idunno.Authentication/issues/29
Oh interesting. Is there a reason that the certificate can't contain the user information and you need to go to a database to replace the generated principal? Identity wasn't meant to be used outside of cookie auth.
The problem you have here is that yes, certificate validation is called on every request. It's an unfortunate side effect of trying to make this cross compatible, and configurable in the normal asp.net core style.
The only thing I can think of is to cache the user information you get back from identity's signin manager in redis or other in memory cache, and use the sha256 hash of the raw data of the certificate as the key, then you'd miss the database hit. You'd have to clear the cache after a while if you want to reflect changes of course.
完成客户端证书 X.509 身份验证后,如何根据数据库中的 AspNetUsers table 对客户端证书 ID 进行身份验证。
如果我将 SignInManager 与 OnValidateCertificate 放在一起,它会在每次请求时被调用,并且 SignInManager 会在每次请求时签署用户。
请告知如何仅调用一次 SignInManager 以使用 AspNetUsers 进行身份验证。 请注意,客户端证书 ID 在 AspNetUsers 中存储为用户名。
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<ApplicationUser>()
.AddRoles<IdentityRole>()
.AddDefaultUI(UIFramework.Bootstrap4)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(options =>
{
options.Events = new CertificateAuthenticationEvents
{
OnValidateCertificate = context =>
{
var claims = new[]
{
new Claim(ClaimTypes.NameIdentifier, context.ClientCertificate.Subject, ClaimValueTypes.String, context.Options.ClaimsIssuer),
new Claim(ClaimTypes.Name, context.ClientCertificate.Subject, ClaimValueTypes.String, context.Options.ClaimsIssuer)
};
context.Principal = new ClaimsPrincipal(new ClaimsIdentity(claims, context.Scheme.Name));
context.Success();
return Task.CompletedTask;
}
};
});
services.AddMvc(config =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
});
}
根据下面 Barry Dorrans 的回复 URL
https://github.com/blowdart/idunno.Authentication/issues/29
Oh interesting. Is there a reason that the certificate can't contain the user information and you need to go to a database to replace the generated principal? Identity wasn't meant to be used outside of cookie auth.
The problem you have here is that yes, certificate validation is called on every request. It's an unfortunate side effect of trying to make this cross compatible, and configurable in the normal asp.net core style.
The only thing I can think of is to cache the user information you get back from identity's signin manager in redis or other in memory cache, and use the sha256 hash of the raw data of the certificate as the key, then you'd miss the database hit. You'd have to clear the cache after a while if you want to reflect changes of course.