m safeCertContext 是无效句柄

m safeCertContext is an invalid handle

我在后端使用证书身份验证,我想使用 HttpClient 使用 Api 这是我的服务代码:

public async Task<List<ReadPoste>> GetPostesAsync(string envName = "AMED")
{
    try
    {

        using var response = await _httpClient.GetAsync($"api/TMCMAPI?envName={envName}");
        var apiResponse = await response.Content.ReadAsStreamAsync();
        List<ReadPoste> readPostes = await JsonSerializer.DeserializeAsync<List<ReadPoste>>(apiResponse, new JsonSerializerOptions
        {
            PropertyNameCaseInsensitive = true,
        });
        //WriteInformationLog("GetPostes", readPostes);
        return readPostes;
    }
    catch (Exception e)
    {
        Log.Error(e, e.Message);
        return new List<ReadPoste>();
    }
}

这是我的 HttpClient 处理程序:

    public class MyHttpClientHandler : HttpClientHandler
    {

        public MyHttpClientHandler()
        {

            using (var cert = GetClientCertificate())
            {
                ClientCertificateOptions = ClientCertificateOption.Manual;
                ClientCertificates.Add(cert);

            }
        }

        private X509Certificate2 GetClientCertificate()
        {

            var store = new X509Store(StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly);
            var clientCertificate = store.Certificates[0];
            return clientCertificate;


        }
    }
}

我的启动配置 HttpClient:

    services.AddHttpClient<ITCMCMClientService, TCMCMClientService>
        (client => { client.BaseAddress = new Uri(Configuration.GetValue<string>("ApexOneBackEnd")); })
            .ConfigurePrimaryHttpMessageHandler<MyHttpClientHandler>();

但是我遇到了这个异常:

System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
 ---> System.Security.Cryptography.CryptographicException: m_safeCertContext is an invalid handle.
   at System.Security.Cryptography.X509Certificates.X509Certificate.ThrowIfInvalid()
   at System.Security.Cryptography.X509Certificates.X509Certificate2.get_HasPrivateKey()
   at System.Net.Security.CertificateHelper.GetEligibleClientCertificate(X509Certificate2Collection candidateCerts)
   at System.Net.Security.CertificateHelper.GetEligibleClientCertificate(X509CertificateCollection candidateCerts)
   at System.Net.Http.HttpClientHandler.<set_ClientCertificateOptions>b__70_0(Object sender, String targetHost, X509CertificateCollection localCertificates, X509Certificate remoteCertificate, String[] acceptableIssuers)
   at System.Net.Security.SslStream.UserCertSelectionCallbackWrapper(String targetHost, X509CertificateCollection localCertificates, X509Certificate remoteCertificate, String[] acceptableIssuers)
   at System.Net.Security.SecureChannel.AcquireClientCredentials(Byte[]& thumbPrint)
   at System.Net.Security.SecureChannel.GenerateToken(Byte[] input, Int32 offset, Int32 count, Byte[]& output)
   at System.Net.Security.SecureChannel.NextMessage(Byte[] incoming, Int32 offset, Int32 count)
   at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.ProcessAuthentication(LazyAsyncResult lazyResult, CancellationToken cancellationToken)
   at System.Net.Security.SslStream.BeginAuthenticateAsClient(SslClientAuthenticationOptions sslClientAuthenticationOptions, CancellationToken cancellationToken, AsyncCallback asyncCallback, Object asyncState)
   at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__65_0(SslClientAuthenticationOptions arg1, CancellationToken arg2, AsyncCallback callback, Object state)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncImpl[TArg1,TArg2](Func`5 beginMethod, Func`2 endFunction, Action`1 endAction, TArg1 arg1, TArg2 arg2, Object state, TaskCreationOptions creationOptions)
   at System.Threading.Tasks.TaskFactory.FromAsync[TArg1,TArg2](Func`5 beginMethod, Action`1 endMethod, TArg1 arg1, TArg2 arg2, Object state, TaskCreationOptions creationOptions)
   at System.Threading.Tasks.TaskFactory.FromAsync[TArg1,TArg2](Func`5 beginMethod, Action`1 endMethod, TArg1 arg1, TArg2 arg2, Object state)
   at System.Net.Security.SslStream.AuthenticateAsClientAsync(SslClientAuthenticationOptions sslClientAuthenticationOptions, CancellationToken cancellationToken)
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean allowHttp2, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.DiagnosticsHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
   at ApexOne.SPA.Data.Services.TCMCMClientService.GetPostesAsync(String envName) in E:\Source\Repos\ApexOne\ApexOne.SPA\Data\Services\TCMCMClientService.cs:line 37

任何人都可以帮助我解决这个问题吗?

我终于得到了问题:使用块后证书从内存中删除,而不是:

 using (var cert = GetClientCertificate())
            {
                ClientCertificateOptions = ClientCertificateOption.Manual;
                ClientCertificates.Add(cert);

            }

我这样做了:

    ClientCertificates.Add(GetClientCertificate());