简体   繁体   English

OnCertificateValidated 未运行 - 自签名证书客户端身份验证 - ASP.NET Core 和 Kestrel

[英]OnCertificateValidated not running - Self-Signed Certificate Client Authentication - ASP.NET Core and Kestrel

I would like to authenticate clients connecting to my ASP.NET Core Web API (.NET 5) running on Kestrel using certificate-based authentication.我想使用基于证书的身份验证对连接到在 Kestrel 上运行的 ASP.NET Core Web API (.NET 5) 的客户端进行身份验证。

In my Startup.cs I have the following in ConfigureServices :在我的Startup.cs我在ConfigureServices有以下内容:

services.AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme)
    .AddCertificate(options =>
    {
        options.AllowedCertificateTypes = CertificateTypes.All;
        options.Events = new CertificateAuthenticationEvents
        {
            OnCertificateValidated = context =>
            {
                // More code to verify certificates
            },
            OnAuthenticationFailed = context =>
            {
                // More code
            }
        };
    });

// Other services

And in Configure :Configure

app.UseHttpsRedirection();

app.UseRouting();

app.UseAuthentication();

app.UseEndpoints(endpoints =>
{
    // Endpoints
});

And in Program.cs I have included:Program.cs我包含了:

webBuilder.ConfigureKestrel(o =>
{
    o.ConfigureHttpsDefaults(o =>
        o.ClientCertificateMode = ClientCertificateMode.RequireCertificate);
});

If I connect to the API in a browser, it prompts me for a certificate, but after I select a certificate, neither the OnCertificateValidated nor the OnAuthenticationFailed events are triggered.如果我连接到API的浏览器,它提示我要证书,但我选择一个证书后,无论是OnCertificateValidated也不OnAuthenticationFailed事件被触发。 After some further testing, I realized that the entire options configuration delegate inside the AddCertificate call in Startup.cs never runs.经过一些进一步的测试,我意识到Startup.cs AddCertificate调用中的整个选项配置委托永远不会运行。 This makes me think I am missing some kind of configuration for Kestrel, but I do not know what that is.这让我觉得我缺少某种 Kestrel 的配置,但我不知道那是什么。 As a note, my Web API does NOT use IIS hosting.请注意,我的 Web API 不使用 IIS 托管。 What else do I need to do to use self-signed certificate-based authentication?我还需要做什么才能使用基于自签名证书的身份验证?

The code I have so far is based on the instructions found in the documentation here: https://docs.microsoft.com/en-us/aspnet/core/security/authentication/certauth?view=aspnetcore-5.0到目前为止,我拥有的代码基于此处文档中的说明: https : //docs.microsoft.com/en-us/aspnet/core/security/authentication/certauth?view=aspnetcore-5.0

Ok, so in the end I was able to solve my own problem.好的,所以最后我能够解决我自己的问题。 There were two different parts to solving it, but ultimately it only required a few small modifications to my project code.解决它有两个不同的部分,但最终只需要对我的项目代码进行一些小的修改。

Recognizing client certificates识别客户端证书

Firstly, the server was not recognizing the self-signed client certificates as valid certificates.首先,服务器未将自签名客户端证书识别为有效证书。 This can be solved by either 1. adding all of the client certificates (or a root CA that signs them all) to the trusted certificate store of the operating system or 2. adding a ClientCertificateValidation callback to kestrel to determine whether or not a certificate is accepted or rejected.这可以通过以下任一方式解决: 1. 将所有客户端证书(或对所有证书进行签名的根 CA)添加到操作系统的可信证书存储中,或者 2. 将ClientCertificateValidation回调添加到 kestrel 以确定证书是否为接受或拒绝。

Example of #2 (an adjustment to the ConfigureHttpsDefaults lambda in Program.cs ) is below: #2 的示例(对Program.csConfigureHttpsDefaults lambda 的调整)如下:

webBuilder.ConfigureKestrel(o =>
{
    o.ConfigureHttpsDefaults(opts =>
    {
        opts.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
        opts.ClientCertificateValidation = (cert, chain, policyErrors) =>
        {
            // Certificate validation logic here
            // Return true if the certificate is valid or false if it is invalid
        };
    });
});

As a side note, calling opts.AllowAnyClientCertificate() is a shorthand for adding a ClientCertificateValidation callback that always returns true, making ALL self-signed certificates valid.作为旁注,调用opts.AllowAnyClientCertificate()是添加始终返回 true 的ClientCertificateValidation回调的简写,使所有自签名证书都有效。


Required Authorization所需授权

After applying either of these approaches, my API would accept queries from valid certificates, but my extra certificate validation logic in the OnCertificateValidated event was still not running.应用这些方法之一后,我的 API 将接受来自有效证书的查询,但我在OnCertificateValidated事件中的额外证书验证逻辑仍未运行。 This is because, according to comments on ASP.NET Core issue #14033 , this event's extra certificate validation will never run unless authorization is enabled for the endpoint being accessed.这是因为,根据对ASP.NET Core 问题 #14033 的评论,除非为正在访问的端点启用授权,否则此事件的额外证书验证将永远不会运行。 This makes sense because this event is often used to generate a ClaimsPrincipal from a certificate per the ASP.NET Core Docs on the subject .这是有道理的,因为此事件通常用于根据主题上的 ASP.NET Core Docs的证书生成ClaimsPrincipal Setting ASP.NET to use authorization and requiring authorization for API calls (eg, by applying the [Authorize] attribute to all controllers) causes the additional authentication checks to run for those API calls.将 ASP.NET 设置为使用授权并要求对 API 调用进行授权(例如,通过将[Authorize]属性应用于所有控制器)会导致对这些 API 调用运行额外的身份验证检查。

app.UseHttpsRedirection();

app.UseRouting();

app.UseAuthentication();

// Adding this and adding the [Authorize] attribute
// to controllers fixes the problem.
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    // Endpoints
});

After this, my OnCertificateValidated event was called for every connection and I was able to perform additional authentication logic and reject invalid certificates.在此之后,每个连接都会调用我的OnCertificateValidated事件,并且我能够执行额外的身份验证逻辑并拒绝无效证书。

The accepted answer was very helpful for me (thanks!) but it did not solve my problem entirely.接受的答案对我很有帮助(谢谢!)但它并没有完全解决我的问题。

I found that the ClientCertificateValidation function is not the only place the certificate is validated (and rejected).我发现ClientCertificateValidation函数不是验证(和拒绝)证书的唯一地方。 Using AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme). AddCertificate...使用AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme). AddCertificate... AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme). AddCertificate... also caused another validation to be triggered, after ClientCertificateValidation was handled. AddAuthentication(CertificateAuthenticationDefaults.AuthenticationScheme). AddCertificate...还导致在处理ClientCertificateValidation之后触发另一个验证。

To solve the problem for me, I had to configure a CustomTrustStore in lines to the CertificateAuthenticationOptions:为了解决我的问题,我必须在CertificateAuthenticationOptions:行中配置CustomTrustStore CertificateAuthenticationOptions:

AddCertificate(options =>
{
    options.AllowedCertificateTypes = CertificateTypes.All;
    options.ChainTrustValidationMode = X509ChainTrustMode.CustomRootTrust;
    options.CustomTrustStore = new X509Certificate2Collection { rootCert };
    options.RevocationMode = X509RevocationMode.NoCheck;
    options.Events = new CertificateAuthenticationEvents
    {
        OnCertificateValidated = context =>
        {
            if (validationService.ValidateCertificate(context.ClientCertificate))
            {
                context.Success();
            }
            else
            {
                context.Fail("invalid cert");
            }

            return Task.CompletedTask;
        },
        OnAuthenticationFailed = context =>
        {
            context.Fail("invalid cert");
            return Task.CompletedTask;
        }
    };
});

Where rootCert is initiated with: rootCert是通过以下方式启动的:

var rootCert = new X509Certificate2("RootCert.pfx", "1234");

And RootCert.pfx is added as file to the project.并且RootCert.pfx作为文件添加到项目中。

Since we're using the built-in validation now from AddAuthentication(.).AddCertificate , we should disable the earlier validation with AllowAnyCertificate() (This validation does not know about our custom root trust):由于我们现在使用AddAuthentication(.).AddCertificate的内置验证,我们应该使用AllowAnyCertificate()禁用较早的验证(此验证不知道我们的自定义根信任):

builder.WebHost.ConfigureKestrel(kso =>
{
    kso.ConfigureHttpsDefaults(cao => {
        cao.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
        cao.AllowAnyClientCertificate();
        cao.CheckCertificateRevocation = false;
    });
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用自签名客户端证书修复 asp.net core 3.1 中的 RevocationStatusUnknown - How to fix RevocationStatusUnknown in asp.net core 3.1 with self-signed client certificate 安全错误,在Azure(Asp.net核心)上发布带有客户端证书(自签名根)的邮件 - Security Error, post with Client Certificate (Self-signed Root) on Azure (Asp.net core) Self Hosted Asp Net Core Web 服务器,使用自签名证书进行客户端身份验证 - Self Hosted Asp Net Core Web server, client authentication with self-signed certificates 无法使用自签名客户端证书来验证对ASP.NET MVC3服务的调用 - Cannot authenticate a call to ASP.NET MVC3 service with a self-signed client certificate Linux上的ASP.NET Core Kestrel从不提示客户端证书 - ASP.NET Core Kestrel on Linux never prompts for client certificate Firefox 中的 ASP.NET Core 自签名证书不起作用 - ASP.NET Core Self Signed Certificate in Firefox not working 在Kestrel服务器上运行ASP.NET Core Angular模板? - Running ASP.NET Core Angular template on Kestrel server? 如何以编程方式创建有效的自签名X509Certificate2,而不是从.NET Core中的文件加载 - How to create a valid, self-signed X509Certificate2 programmatically, not loading from file in .NET Core 将自签名 ssl 证书添加到 gcp 容器化 .net core web vm 实例 - Add self-signed ssl certificate to gcp containerized .net core web vm instance 专用服务器/客户端的自签名证书安全性 - Self-signed certificate security for private server/client
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM