我正在尝试使用 ASP.NET Core 9 实现基于证书的身份验证,遵循官方文档:在 ASP.NET Core 中配置证书身份验证
我想出了这个基本的实现:
using Microsoft.AspNetCore.Authentication.Certificate;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Https;
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<KestrelServerOptions>(options =>
{
options.ConfigureHttpsDefaults(options =>
{
options.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
});
});
builder.Services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
.AddCertificate(options =>
{
options.AllowedCertificateTypes = CertificateTypes.All;
options.Events = new CertificateAuthenticationEvents
{
OnCertificateValidated = context =>
{
Console.WriteLine($"Validating: {context.ClientCertificate.Subject}");
if (context.ClientCertificate.Subject == "Pragmateek")
context.Success();
else
context.Fail("Invalid certificate.");
return Task.CompletedTask;
}
};
});
var app = builder.Build();
app.UseAuthentication();
app.MapGet("/", () => "Hello World!");
app.Run();
从 Chrome 请求资源时,我收到一个弹出窗口,要求我选择证书,我选择了使用
New-SelfSignedCertificate -Subject "CN=Pragmateek" -CertStoreLocation cert:\CurrentUser
生成的证书,但出现了 ERR_BAD_SSL_CLIENT_AUTH_CERT
错误。
并且
OnCertificateValidated
中的验证代码永远不会被调用。
如果重要的话,项目是使用基本模板
dotnet new web --name ...
创建的,并使用 dotnet run --launch-profile https
运行(并且使用 Visual Studio 运行它不会改变任何内容)。
缺少什么管道?
问题在于 Kestrel 似乎使用默认的客户端证书验证,该验证会出于未知原因拒绝证书。
解决方案是允许任何带有
options.AllowAnyClientCertificate();
的证书,它会用真实的回调覆盖 ClientCertificateValidation
:
builder.Services.Configure<KestrelServerOptions>(options =>
{
options.ConfigureHttpsDefaults(options =>
{
options.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
options.AllowAnyClientCertificate();
});
});