8.1SSL 证书与网络连接

这里汇总了一些发送 HTTP 远程请求时可能遇到的常见问题。

常见问题#

这里汇总了一些发送 HTTP 远程请求时可能遇到的常见问题。

忽略 SSL 证书验证(https 错误)#

若发送 HTTP 远程请求过程中出现 The SSL connection could not be established, see inner exception. 的证书错误问题,您可以通过添加以下配置来忽略 SSL 证书验证:

cs
// 默认客户端配置services.AddHttpClient(string.Empty)    .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler    {        // 忽略 SSL 证书验证        ServerCertificateCustomValidationCallback = HttpRemoteUtility.IgnoreSslErrors,        SslProtocols = HttpRemoteUtility.AllSslProtocols    });// 若使用 SocketsHttpHandler,可以通过以下配置来忽略 SSL 证书验证services.AddHttpClient(string.Empty)    .ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler()    {        SslOptions = new SslClientAuthenticationOptions        {            // 忽略 SSL 证书验证            RemoteCertificateValidationCallback = HttpRemoteUtility.IgnoreSocketSslErrors,            EnabledSslProtocols = HttpRemoteUtility.AllSslProtocols        },    });

除了可以在全局配置中忽略 SSL 证书验证外,您还可以通过 SetHttpClientProvider 方法为单次请求单独设置忽略 SSL 证书验证。示例代码如下:

cs
HttpRequestBuilder.Get("https://furion.net/")    .SetHttpClientProvider(() => (new HttpClient(new HttpClientHandler    {        // 忽略 SSL 证书验证        ServerCertificateCustomValidationCallback = HttpRemoteUtility.IgnoreSslErrors,        SslProtocols = HttpRemoteUtility.AllSslProtocols    }), client => client.Dispose()));

发送请求出现长时间挂起或阻塞#

若发送 HTTP 远程请求时,出现长时间挂起或阻塞,可能是您在构造请求时使用了类似以下方式获取本机 IPMAC 地址

cs
var addressList = Dns.GetHostEntry(Dns.GetHostName()).AddressList;

Dns.GetHostName() 获取本机主机名,Dns.GetHostEntry(主机名) 则会通过 DNSNetBIOS 等机制解析该名称。如果主机名未在 DNS 中注册或 DNS 服务器不可达,解析过程会一直等待直到系统超时(Windows 默认约 10~15 秒),导致每个请求都被阻塞。

此时,可使用框架内置的 HttpRemoteUtility 工具方法替代,它们直接读取本地网络接口信息,完全无 DNS/NetBIOS 查询,执行时间 < 1 毫秒

cs
// 获取本机 IPv4 地址var ip = HttpRemoteUtility.GetLocalIPv4();// 获取本机 MAC 地址var mac = HttpRemoteUtility.GetLocalMacAddress();

采用上述方法即可消除因本机主机名解析导致的长时间阻塞,恢复正常的 HTTP 请求响应速度。

强制 IPv4IPv6 请求#

通过配置 SocketsHttpHandlerConnectCallback,可强制 HttpClient 使用指定 IP 版本或本地出口地址发起请求,适用于网络策略控制或多网卡环境,,以优化性能或满足网络要求。示例如下:

cs
// 强制 IPv4services.AddHttpClient(string.Empty)    .ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler    {        ConnectCallback = HttpRemoteUtility.IPv4ConnectCallback    });// 强制 IPv6services.AddHttpClient(string.Empty)    .ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler    {        ConnectCallback = HttpRemoteUtility.IPv6ConnectCallback    });// 默认(自动选择)services.AddHttpClient(string.Empty)    .ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler    {        ConnectCallback = HttpRemoteUtility.UnspecifiedConnectCallback    });// 多网卡场景:指定本地出口 IPv4services.AddHttpClient(string.Empty)    .ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler    {        ConnectCallback = (context, token) =>                HttpRemoteUtility.ConnectWithLocalIPv4(IPAddress.Parse("192.168.0.103"), context, token)    });// 多网卡场景:指定本地出口 IPv6services.AddHttpClient(string.Empty)    .ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler    {        ConnectCallback = (context, token) =>                HttpRemoteUtility.ConnectWithLocalIPv6(IPAddress.Parse("::1"), context, token)    });

重定向响应处理#

在发送 HTTP 远程请求时,若目标服务器返回重定向响应(如 301 Moved Permanently302 Found 等),框架默认会自动跟随重定向。为精确处理这些情况,可参考以下方案:

  • 通过 HttpRemoteOptions 全局启用或禁用自动重定向

在发送 HTTP 远程请求时,若目标服务器返回重定向响应(如 301 Moved Permanently302 Found 等),框架默认会自动跟随重定向。要启用或禁用这一行为,可以通过以下配置进行设置:

cs
services.AddHttpRemote(builder => {})    .ConfigureOptions(options =>    {        // 设置指示请求是否应遵循重定向响应,默认 true        options.AllowAutoRedirect = false;        // 设置请求所遵循的最大重定向数,默认 50 次        options.MaximumAutomaticRedirections = 50;    });
  • 通过 HttpClient 全局启用或禁用自动重定向

若希望或不希望 HttpClient 自动处理重定向,可通过配置 HttpClientHandlerSocketsHttpHandler 来启用或禁用此功能。

cs
// 配置默认客户端services.AddHttpClient(string.Empty)    .ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler    {        AllowAutoRedirect = true,   // 允许自动重定向,默认为 true (允许)        MaxAutomaticRedirections = 20 // 设置最大重定向次数    });
  • 通过手动处理重定向

也可以检查响应状态码。若状态码在 300-399 范围内,表明为重定向状态码,此时可手动解析 Location 头,并使用该地址重新发送请求。

  1. 禁用 HttpClient 的自动重定向功能
cs
// 配置默认客户端services.AddHttpClient(string.Empty)    .ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler    {        AllowAutoRedirect = false    });
  1. 手动管理重定向流程
cs
var responseMessage = await httpRemoteService.GetAsync("https://furion.net/redirect");// 检查响应消息是否包含重定向状态码var statusCode = responseMessage.StatusCode;// 通常应使用 while 循环来进行判断,因为可能涉及多次重定向if (statusCode is HttpStatusCode.Ambiguous or HttpStatusCode.Moved or HttpStatusCode.Redirect or HttpStatusCode.RedirectMethod or HttpStatusCode.RedirectKeepVerb || (int)statusCode == 308){    // 获取重定向地址    var redirectUrl = responseMessage.Headers.Location;    if (redirectUrl != null)    {        // 用新的 URL 再次发送请求        response = await httpRemoteService.GetAsync(redirectUrl);    }}

选择哪种方法取决于您的具体需求。如果你需要更细粒度地控制每个重定向过程,比如记录日志或执行特定逻辑,那么手动处理可能是更好的选择。如果只是简单地想要让客户端自动处理所有重定向,则开启自动重定向更加方便。