。netcore 3带有HttpClient的客户端证书

问题描述 投票:0回答:1

我有一个.netcore 3项目(WorkerService模板),该项目将JSON数据发送到REST端点。请求通过HttpClient发送,并配置为使用服务器所需的客户端证书。服务器响应始终为200和HTML字符。根据服务器管理者的说法,该请求被重定向到Web服务器的主页,因为客户端计算机已由特定用户正确处理,但没有证书可用。我正在使用以下代码:

public void ConfigureServices(IServiceCollection services)
{
  services.AddHttpClient("client").ConfigurePrimaryHttpMessageHandler(() => 
  {
    var handler = new HttpClientHandler();
    handler.ClientCertificateOptions = ClientCertificateOption.Manual;
    handler.SslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12;
    handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;
    X509Certificate2 certificate = GetCertificate(Configuration.CertificateSubjectKeyIdentifier);
    handler.ClientCertificates.Add(certificate);
    return handler;
  }
}

GetCertificate从证书存储中检索证书:

    private X509Certificate2 GetCertificate(string subjectIdentifier)
    {
        X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
        store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);

        var collection = store.Certificates;
        var certificates = collection.Find(X509FindType.FindBySubjectKeyIdentifier, subjectIdentifier, true);
        foreach (var certificate in certificates)
        {
            if (DateTime.Compare(DateTime.Parse(certificate.GetExpirationDateString()), DateTime.Now) >= 0)
            {

                Logger.LogInformation($"Loaded X.509 certificate {certificate.Subject} issued by {certificate.Issuer}, valid from {certificate.GetEffectiveDateString()} to {certificate.GetExpirationDateString()}");
                return certificate;
            }
        }

        Logger.LogError($"X.509 certificate not loaded: No valid certificate could be found.");
        return null;
    }

发送请求的代码:

public async Task<ResponseData> PostAsync<T>(string url, T dataToSend)
    {
        ResponseData result = null;
        HttpResponseMessage httpResponseMessage = null;

        try
        {
            var errorHttp = false;
            HttpClient httpClient;
            using (httpClient = HttpClientFactory.CreateClient("client)) // IHttpClientFactory initialized in ctor
            {
                HttpContent httpContent;
                using (httpContent = CreateJsonHttpContent(dataToSend, MediaType.ApplicationJson)) //build JSON from data
                {  
                    httpResponseMessage = await httpClient.PostAsync(url, httpContent).ConfigureAwait(false);

                    result = BuildResponseData(httpResponseMessage); //writes response data in a class

                    if (httpResponseMessage?.IsSuccessStatusCode == true)
                    {
                        result.Content = await httpResponseMessage.Content.ReadAsStringAsync().ConfigureAwait(false);
                    }
                    else
                    {
                        errorHttp = true;
                    }

                    if (errorHttp)
                    {
                        var httpRequestException = new HttpRequestException($"The http request to {url} was not successful.");
                        Logger.LogError($"{httpRequestException.Message} : {httpRequestException.InnerException}");
                        Logger.LogError(httpRequestException.StackTrace);
                    }
                }
            }
        }
        catch (SocketException socketException)
        {
            Logger.LogError($"{socketException.Message} : {socketException.InnerException}");
            result = new ResponseData(socketException);
        }
        catch (WebException wex)
        {
            Logger.LogError($"{wex.Message} : {wex.InnerException}");
            if (wex.Status == WebExceptionStatus.ConnectFailure || wex.Status == WebExceptionStatus.Timeout)
            {
                Logger.LogError($"Cannot connect to the rest service : {WebExceptionStatus.Timeout}");
            }
        }
        catch (Exception ex)
        {

            LogException(ref ex);
            result = new ResponseData(ex);
        }
        finally
        {
            httpResponseMessage?.Dispose();
        }

        return result;
    }

使用PostAsync方法的类也已在ServiceCollection中注册。有什么想法在这里可能出什么问题吗?也可能是服务器端未正确处理证书吗?

rest .net-core x509certificate2
1个回答
0
投票

我强烈怀疑客户端(您)端的配置错误。您的应用程序从LocalMachine存储中读取证书。默认情况下,只有本地管理员和SYSTEM帐户可以读取/使用私钥安装在LocalMachine存储中的证书。

或者,将证书安装在运行客户端应用程序的用户帐户的CurrentUser存储中,或显式授予私钥权限给运行客户端应用程序的用户帐户。为此:

  1. LocalMachine上下文中打开证书MMC管理单元(certlm.msc
  2. 展开Personal\Certificates
  3. 选择所需的证书,单击鼠标右键,然后单击Manage Private Keys菜单项。
  4. 向运行客户端应用程序的用户帐户授予Read权限。

在这种情况下,您不需要修改代码或在商店之间移动证书。

© www.soinside.com 2019 - 2024. All rights reserved.