【问题标题】:Client certificate not included by HttpClientHandler in .net core.net 核心中的 HttpClientHandler 不包含客户端证书
【发布时间】:2020-08-24 18:02:57
【问题描述】:

我在使用 HttpClientHandler 发送证书时遇到困难,因为证书根本不会出现在服务器的请求中。该证书具有用于服务器和客户端身份验证的正确 EKU,以及“数字签名”的密钥用法。 @davidsh 将问题 26531 视为 HttpClient 缺少日志记录,但在 Visual Studio 中运行我的项目(日志设置为 Trace 并使用 dotnet 3.1.401)没有出现输出错误。我对 logman 一点也不熟悉,但是当我执行代码时应该发生问题时我运行了它,并且日志中没有任何内容表明问题可能是什么。用尽了测试代码的选项我试图在客户端请求中添加不带私钥的证书,以查看httpClientHandler.ClientCertificates.Add ... 是否会抛出任何错误,例如“您需要带有私钥的证书来签署您的请求”,不应该说什么吗?

在客户端:

services.AddHttpClient<ILetterManClient, LetterManClient.LetterManClient>()
    .ConfigureHttpClient(client =>
    {
        client.BaseAddress = new Uri(configuration.GetValue<string>("Microservices:LetterManAPI"));
    })
    .ConfigurePrimaryHttpMessageHandler(() =>
    {
        HttpClientHandler httpClientHandler = new HttpClientHandler();

        httpClientHandler.ServerCertificateCustomValidationCallback = ValidateServiceCertficate;
        httpClientHandler.ClientCertificateOptions = ClientCertificateOption.Manual;

        clientCertificate = new X509Certificate2("client_cert.pfx", "developer");

        httpClientHandler.ClientCertificates.Add(clientCertificate);

        return httpClientHandler;
    });

在服务器上:

public class ValidateClientCertificates : TypeFilterAttribute
{
    public ValidateClientCertificates() : base(typeof(ValidateClientCertificatesImpl))
    {

    }

    private class ValidateClientCertificatesImpl : IAsyncAuthorizationFilter
    {
        X509Certificate2 clientCertificate;
        public ValidateClientCertificatesImpl(IConfiguration configuration, IWebHostEnvironment webHostEnvironment)
        {
            clientCertificate = new X509Certificate2("client_cert.crt");
        }

        public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            var certificate = await context.HttpContext.Connection.GetClientCertificateAsync();

            if ((certificate == null) || (!certificate.Thumbprint.Equals(clientCertificate.Thumbprint)))
            {
                context.Result = new UnauthorizedObjectResult("");
                return;
            }
        }
    }
}

旁注: 我也一直在尝试使用从 corefx 存储库编译的代码来调试我的项目,以查看发生了什么,但 Visual Studio 坚持引用本地安装的 sdk 中的代码,而不是引用它的 corefx 中的项目,但这是另一个问题。

我创建了模拟问题的this project。它创建证书,并且有两个项目,一个服务和另一个客户端实现。

我们将非常欢迎任何帮助。

【问题讨论】:

    标签: .net-core certificate httpclient x509certificate


    【解决方案1】:

    These 是 Kestrel 要求客户端证书的准则,但它假定 CA 已安装在机器中,否则您必须在配置 Kestrel 服务器时直接指定客户端证书,如下所示:

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
                webBuilder.ConfigureKestrel(o =>
                {
                    o.ConfigureHttpsDefaults(o => {
                        o.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
                        o.ClientCertificateValidation = ValidateClientCertficate;
                    });
                });
            });
    
    public static Func<X509Certificate, X509Chain, SslPolicyErrors, bool> ValidateClientCertficate =
        delegate (X509Certificate serviceCertificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            X509Certificate2 clientCertificate;
            clientCertificate = new X509Certificate2("client.crt");
    
            if (serviceCertificate.GetCertHashString().Equals(clientCertificate.Thumbprint))
            {
                return true;
            }
    
            return false;
        };
    

    很遗憾,您不能像我预期的那样要求特定路由的客户端证书。

    【讨论】:

      猜你喜欢
      • 2020-07-08
      • 2011-09-28
      • 2018-04-07
      • 1970-01-01
      • 2018-02-28
      • 2015-04-17
      • 2021-08-15
      • 2022-07-01
      • 1970-01-01
      相关资源
      最近更新 更多