将客户端证书添加到

将客户端证书添加到

本文介绍了将客户端证书添加到 .NET Core HttpClient的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 .NET Core 并构建一个利用支付 API 的 API.有一个客户端证书需要添加到双向 SSL 身份验证的请求中.如何在 .NET Core 中使用 HttpClient 实现这一点?

I was playing around with .NET Core and building an API that utilizes payment APIs. There's a client certificate that needs to be added to the request for two-way SSL authentication.How can I achieve this in .NET Core using HttpClient?

我查看了各种文章,发现 HttpClientHandler 没有提供任何添加客户端证书的选项.

I have looked at various articles and found that HttpClientHandler doesn't provide any option to add client certificates.

推荐答案

像这样在 Main() 中进行所有配置:

Make all configuration in Main() like this:

public static void Main(string[] args)
{
    var configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
    var logger = new LoggerConfiguration().ReadFrom.Configuration(configuration).CreateLogger();
    string env="", sbj="", crtf = "";

    try
    {
        var whb = WebHost.CreateDefaultBuilder(args).UseContentRoot(Directory.GetCurrentDirectory());

        var environment = env = whb.GetSetting("environment");
        var subjectName = sbj = CertificateHelper.GetCertificateSubjectNameBasedOnEnvironment(environment);
        var certificate = CertificateHelper.GetServiceCertificate(subjectName);

        crtf = certificate != null ? certificate.Subject : "It will after the certification";

        if (certificate == null) // present apies even without server certificate but dont give permission on authorization
        {
            var host = whb
                .ConfigureKestrel(_ => { })
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseIISIntegration()
                .UseStartup<Startup>()
                .UseConfiguration(configuration)
                .UseSerilog((context, config) =>
                {
                    config.ReadFrom.Configuration(context.Configuration);
                })
                .Build();
            host.Run();
        }
        else
        {
            var host = whb
                .ConfigureKestrel(options =>
                {
                    options.Listen(new IPEndPoint(IPAddress.Loopback, 443), listenOptions =>
                    {
                        var httpsConnectionAdapterOptions = new HttpsConnectionAdapterOptions()
                        {
                            ClientCertificateMode = ClientCertificateMode.AllowCertificate,
                            SslProtocols = System.Security.Authentication.SslProtocols.Tls12,
                            ServerCertificate = certificate
                        };
                        listenOptions.UseHttps(httpsConnectionAdapterOptions);
                    });
                })
                .UseContentRoot(Directory.GetCurrentDirectory())
                .UseIISIntegration()
                .UseUrls("https://*:443")
                .UseStartup<Startup>()
                .UseConfiguration(configuration)
                .UseSerilog((context, config) =>
                {
                    config.ReadFrom.Configuration(context.Configuration);
                })
                .Build();
            host.Run();
        }

        Log.Logger.Information("Information: Environment = " + env +
            " Subject = " + sbj +
            " Certificate Subject = " + crtf);
    }
    catch(Exception ex)
    {
        Log.Logger.Error("Main handled an exception: Environment = " + env +
            " Subject = " + sbj +
            " Certificate Subject = " + crtf +
            " Exception Detail = " + ex.Message);
    }
}

像这样配置文件startup.cs:

#region 2way SSL settings
services.AddMvc();
services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = CertificateAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = CertificateAuthenticationDefaults.AuthenticationScheme;
})
.AddCertificateAuthentication(certOptions =>
{
    var certificateAndRoles = new List<CertficateAuthenticationOptions.CertificateAndRoles>();
    Configuration.GetSection("AuthorizedCertficatesAndRoles:CertificateAndRoles").Bind(certificateAndRoles);
    certOptions.CertificatesAndRoles = certificateAndRoles.ToArray();
});

services.AddAuthorization(options =>
{
    options.AddPolicy("CanAccessAdminMethods", policy => policy.RequireRole("Admin"));
    options.AddPolicy("CanAccessUserMethods", policy => policy.RequireRole("User"));
});
#endregion

证书助手

public class CertificateHelper
{
    protected internal static X509Certificate2 GetServiceCertificate(string subjectName)
    {
        using (var certStore = new X509Store(StoreName.Root, StoreLocation.LocalMachine))
        {
            certStore.Open(OpenFlags.ReadOnly);
            var certCollection = certStore.Certificates.Find(
                                       X509FindType.FindBySubjectDistinguishedName, subjectName, true);
            X509Certificate2 certificate = null;
            if (certCollection.Count > 0)
            {
                certificate = certCollection[0];
            }
            return certificate;
        }
    }

    protected internal static string GetCertificateSubjectNameBasedOnEnvironment(string environment)
    {
        var builder = new ConfigurationBuilder()
         .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile($"appsettings.{environment}.json", optional: false);

        var configuration = builder.Build();
        return configuration["ServerCertificateSubject"];
    }
}

这篇关于将客户端证书添加到 .NET Core HttpClient的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-03 21:01