c# - 使用带有自定义 HttpClientHandler 和硬件令牌的 HttpClient 连接到 API 的问题
问题描述
我目前正在开发一个需要定期向 API 发送请求并尽可能长时间保持活动状态的客户端。
我们在物理令牌上使用证书并检查它是否正常工作,我们签署一些数据并尝试建立与 API 的新连接。
实际上有几个工作人员并行发送不同类型的请求,每个工作人员都托管在不同的 ASP.NET Core 后台服务上:
- 一个发送有关要下载的文件的请求并下载它们
- 一个上传文件
- 一个检查令牌是否工作
第三个目前每次检查之间的间隔约为 150 秒,并且在每次迭代中,我们使用自定义的 HttpClientHandler 创建一个新的 HttpClient。在 HttpClientHandler 中,我们设置了一个自定义验证回调(我们在一个测试平台上,现在我们只返回 true)、证书和 ssl 协议(我们尝试了任何组合)
在客户端正常工作一段时间后(它持续了 20 分钟到最长约 20 小时),它开始给出一些错误,如下所示:
System.Net.Http.HttpRequestException: An error occurred while sending the request.
---> System.IO.IOException: The read operation failed, see inner exception.
---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
---> System.ComponentModel.Win32Exception (0x80090304): Impossible to contact local security authority --- End of inner exception stack trace ---
at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Boolean receiveFirst, Byte[] reAuthenticationData, Boolean isApm)
at System.Net.Security.SslStream.ReplyOnReAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Byte[] buffer)
at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](TIOAdapter adapter, Memory`1 buffer)
--- End of inner exception stack trace ---
at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](TIOAdapter adapter, Memory`1 buffer)
at System.Net.Http.HttpConnection.FillAsync(Boolean async)
at System.Net.Http.HttpConnection.ReadNextResponseHeaderLineAsync(Boolean async, Boolean foldedHeadersAllowed)
at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.SendAsyncCore(HttpRequestMessage request, HttpCompletionOption completionOption, Boolean async, Boolean emitTelemetryStartStop, CancellationToken cancellationToken)
在互联网上检查时,此错误不会导致任何结果,希望这里有一些 .NET 专家可以帮助我们。
我们开始使用带有命名客户端的 HttpClientFactory,但它只会导致更少的错误,我们尝试切换到效率更低的方法,结果只会变得更糟。
有 4 件有趣/令人沮丧的事情:
- 下载文件的服务可以正常工作
- 如果我们重新启动它,一切都会开始正常工作
- 有时错误会在几个小时后消失(~5/8),然后又开始正常工作
- 我们有一个使用 SslStream 并发出原始 HTTP 请求的旧客户端,它完全没有问题
任何帮助和/或建议将不胜感激
编辑:添加了两个代码示例,我在其中创建客户端并发送请求,并没有做任何特别的事情
if (!_loggedIn) await Login();
var httpRequest = new HttpRequestMessage
{
Content = new StringContent(request.XmlContent, Encoding.UTF8, "text/xml"),
Method = HttpMethod.Post,
RequestUri = new Uri(_baseUrl)
};
return await SendAsync(httpRequest);
services.AddTransient<CustomHttpClient>(provider =>
{
var handler = new HttpClientHandler
{
SslProtocols = SslProtocols.None,
AllowAutoRedirect = false,
MaxConnectionsPerServer = 5,
ClientCertificates = {new AuthCertificateContext(issuer, pin).GetCertificate()},
ServerCertificateCustomValidationCallback = (_, _, _, _) => true
};
return new CustomHttpClient(new HttpClient(handler, true), number);
});
解决方案
推荐阅读
- git - 如何git合并整个文件?
- javascript - 使用Javascript从下拉列表中获取未定义的值/文本
- ms-access - 如何在已经组合了 2 个查询的联合中添加 1 个没有任何匹配的表
- php - 如何使用 Laravel 中的路由将循环下拉值从视图传递到控制器?
- php - 转换为十进制时缺少前导零
- python - 不使用 SerializerMethodField 显示添加的字段
- spotfire - 是否可以在spotfire中从长字符串中提取固定格式的字符串?
- android - 如何更改 SwitchPreference 上的文本摘要颜色
- c# - 接收数据时,[serialport_datareceived]事件发生多次(使用虚拟串口)
- r - 从文件夹导入时缺少数据