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());
我在后端使用证书身份验证,我想使用 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());