.NetCore Flurl.Http 升级到4.0后 https 无法建立SSL连接

Flurl.Http-3.2.4 升级到 4.0.0 版本后,https请求异常:Call failed. The SSL connection could not be established.

如下图:

Flurl.Http-3.2.4版本绕过https的代码,对于 Flurl.Http-4.0.0 版本来说方法不再适用,3.2.4及4.0.0版本绕过https代码成果在文章最后有展示

查看了Flurl.Http4.0的文档,地址:Configuration - Flurl

配置相关文档内容简单翻译(翻译可能不够精准,请点击上面链接查看官方文档)如下:

配置
Flurl.Http 包含一组强大的选项和技术,用于在各个级别配置其行为。

设置
Flurl 主要通过 Settings上可用的属性进行配置。以下是可用的设置:IFlurlClient IFlurlRequest IFlurlClientBuilder HttpTest

SettingTypeDefault Value
TimeoutTimeSpan?100 seconds
HttpVersionstring"1.1"
AllowedHttpStatusRangestringnull ("2xx,3xx", effectively)
Redirects.Enabledbooltrue
Redirects.AllowSecureToInsecureboolfalse
Redirects.ForwardHeadersboolfalse
Redirects.ForwardAuthorizationHeaderboolfalse
Redirects.MaxAutoRedirectsint10
JsonSerializerISerializerDefaultJsonSerializer
UrlEncodedSerializerISerializerUrlEncodedSerializer

所有属性都是读/写的,可以直接设置:

// set default on the client:
var client = new FlurlClient("https://some-api.com");
client.Settings.Timeout = TimeSpan.FromSeconds(600);
client.Settings.Redirects.Enabled = false;

// override on the request:
var request = client.Request("endpoint");
request.Settings.Timeout = TimeSpan.FromSeconds(1200);
request.Settings.Redirects.Enabled = true;

您还可以流畅地配置它们:

clientOrRequest.WithSettings(settings => {
    settings.Timeout = TimeSpan.FromSeconds(600);
    settings.AllowedHttpStatusRange = "*";
    settings.Redirects.Enabled = false;
})...


或者在很多情况下甚至更流利:

clientOrRequest
    .WithTimeout(600)
    .AllowAnyHttpStatus()
    .WithAutoRedirect(false)
    ...


当同时使用客户端、请求和流畅配置时,您需要密切关注正在配置的对象,因为它可以确定对该客户端的后续调用是否受到影响:

await client
    .WithSettings(...) // configures the client, affects all subsequent requests
    .Request("endpoint") // creates and returns a request
    .WithSettings(...) // configures just this request
    .GetAsync();


无客户端模式支持所有相同的扩展方法。配置并发送请求而无需显式引用客户端:

var result = await "https://some-api.com/endpoint"
    .WithSettings(...) // configures just this request
    .WithTimeout(...) // ditto
    .GetJsonAsync<T>();


上述所有设置和扩展方法也可以在 上使用IFlurlClientBuilder,这对于在启动时进行配置非常有用:

// clientless pattern, all clients:
FlurlHttp.Clients.WithDefaults(builder =>
    builder.WithSettings(...));

// clientless pattern, for a specific site/service:
FlurlHttp.ConfigureClientForUrl("https://some-api.com")
    .WtihSettings(...);

// DI pattern:
services.AddSingleton<IFlurlClientCache>(_ => new FlurlClientCache()
    // all clients:
    .WithDefaults(builder =>
        builder.WithSettings(...))
    // specific named client:
    .Add("MyClient", "https://some-api.com", builder =>
        builder.WithSettings(...))


Settings支持(以及所有相关的流畅优点)的第四个也是最后一个对象是HttpTest,并且它优先于所有内容:

using var test = new HttpTest.AllowAnyHttpStatus();
await sut.DoThingAsync(); // no matter how things are configured in the SUT,
                          // test settings always win 


序列化器
和设置值得特别注意JsonSerializer。UrlEncodedSerializer正如您所料,它们分别控制(反)序列化 JSON 请求和响应以及 URL 编码的表单帖子的详细信息。两者都实现了ISerializer,定义了 3 个方法:

string Serialize(object obj);
T Deserialize<T>(string s);
T Deserialize<T>(Stream stream);
Flurl 为两者提供了默认实现。您不太可能需要使用不同的UrlEncodedSerializer,但您可能出于以下几个原因想要更换JsonSerializer:

  1. 您更喜欢3.x 及更早版本的基于Newtonsoft的版本。(4.0 将其替换为基于System.Text.Json的版本。)这可以通过 Flurl.Http.Newtsonsoft配套包获得。

  2. 您想要使用默认实现,但使用自定义JsonSerializerOptions。这可以通过提供您自己的实例来完成:

clientOrRequest.Settings.JsonSerializer = new DefaultJsonSerializer(new JsonSerializerOptions {
    PropertyNameCaseInsensitive = true,
    IgnoreReadOnlyProperties = true
});

事件处理程序
将日志记录和错误处理等横切关注点与正常逻辑流程分开通常会产生更清晰的代码。Flurl.Http 定义了 4 个事件 - BeforeCall、AfterCall、OnError和OnRedirect- 以及、和EventHandlers上的集合。(与 不同,事件处理程序在 上不可用。)IFlurlClient IFlurlRequest IFlurlClientBuilder Settings HttpTest

与 类似Settings,所有具有EventHandlers属性的东西都会带来一些流畅的快捷方式:

clientOrRequest
    .BeforeCall(call => DoSomething(call)) // attach a synchronous handler
    .OnError(call => LogErrorAsync(call))  // attach an async handler

在上面的示例中,call是 的一个实例FlurlCall,其中包含与请求和响应的各个方面相关的一组可靠的信息和选项:

IFlurlRequest Request
HttpRequestMessage HttpRequestMessage
string RequestBody
IFlurlResponse Response
HttpResponseMessage HttpResponseMessage
FlurlRedirect Redirect
Exception Exception
bool ExceptionHandled
DateTime StartedUtc
DateTime? EndedUtc
TimeSpan? Duration
bool Completed
bool Succeeded


OnError在 之前触发AfterCall,并让您有机会决定是否允许异常冒泡:

clientOrRequest.OnError(async call => {
    await LogTheErrorAsync(call.Exception);
    call.ExceptionHandled = true; // otherwise, the exeption will bubble up
});

OnRedirect允许精确处理 3xx 响应:

clientOrRequest.OnRedirect(call => {
    if (call.Redirect.Count > 5) {
        call.Redirect.Follow = false;
    }
    else {
        log.WriteInfo($"redirecting from {call.Request.Url} to {call.Redirect.Url}");
        call.Redirect.ChangeVerbToGet = (call.Response.Status == 301);
        call.Redirect.Follow = true;
    }
});

在较低级别,事件处理程序是实现 的对象IFlurlEventHandler,它定义了 2 个方法:

void Handle(FlurlEventType eventType, FlurlCall call);
Task HandleAsync(FlurlEventType eventType, FlurlCall call);


通常,您只需要实现一个或另一个,因此 Flurl 提供了一个默认实现 ,FlurlEventHanler它构成了一个方便的基类 - 两种方法都是虚拟无操作的,因此只需重写您需要的方法即可。处理程序可以这样分配:

clientOrRequest.EventHandlers.Add((FlurlEventType.BeforeCall, new MyEventHandler()));


请注意,EventHanlers项目的类型为Tuple<EventType, IFlurlEventHandler>。保持处理程序与偶数类型分离意味着给定的处理程序可以重用于不同的事件类型。

您可能更喜欢基于对象的方法而不是前面描述的更简单的基于 lambda 的方法,原因之一是如果您使用 DI 并且您的处理程序需要注入某些依赖项:

public interface IFlurlErrorLogger : IFlurlEventHandler { }

public class FlurlErrorLogger : FlurlEventHandler, IFlurlErrorLogger
{
    private readonly ILogger _logger;

    public FlurlErrorLogger(ILogger logger) {
        _logger = logger;
    }
}

以下是如何使用 Microsoft 的 DI 框架进行连接:

// register ILogger:
services.AddLogging();
// register service that implements IFlurlEventHander and has dependency on ILogger
services.AddSingleton<IFlurlErrorLogger, FlurlErrorLogger>();

// register event hanlder with Flurl, using IServiceProvider to wire up dependencies:
services.AddSingleton<IFlurlClientCache>(sp => new FlurlClientCache()
    .WithDefaults(builder =>
        builder.EventHandlers.Add((FlurlEventType.OnError, sp.GetService<IFlurlErrorLogger>()))

消息处理程序
Flurl.Http 构建于 之上HttpClient,它(默认情况下)使用它HttpClientHandler来完成大部分繁重的工作。IFlurlClientBuilder公开配置两者的方法:

// clientless pattern:
FlurlHttp.Clients.WithDefaults(builder => builder
    .ConfigureHttpClient(hc => ...)
    .ConfigureInnerHandler(hch => {
        hch.Proxy = new WebProxy("https://my-proxy.com");
        hch.UseProxy = true;
    }));

// DI pattern: 
services.AddSingleton<IFlurlClientCache>(_ => new FlurlClientCache()
    .WithDefaults(builder => builder.
        .ConfigureHttpClient(hc => ...)
        .ConfigureInnerHandler(hch => ...)));

温馨提示:

1、Flurl 禁用AllowAutoRedirect和UseCookies以便重新实现自己的这些功能概念。如果您将 via 设置为 true ConfigureInnerHander,则可能会破坏 Flurl 中的这些功能。
2、DefaultRequestHeaders Flurl 还实现了自己的和概念Timeout,因此您可能不需要配置HttpClient.

也许您已经阅读过SocketsHttpHandler并且想知道如何在 Flurl 中使用它。您可能会惊讶地发现您可能已经是这样了。如前所述,FlurlClient将其大部分工作委托给HttpClient,而后者又将其大部分工作委托给HttpClientHandler。但鲜为人知的是,自 .NET Core 2.1 以来,HttpClientHandler几乎将所有工作委托给SocketsHttpHandler所有支持它的平台,这基本上是除基于浏览器(即 Blazor)平台之外的所有平台。(如果需要说服力,请浏览源代码。) 

FlurlClient → HttpClient → HttpClientHandler → SocketsHttpHandler (on all supported platforms) 

HttpClientHandler尽管如此,您可能还是想绕过并直接使用,有一个原因SocketsHttpHander:它的某些可配置性HttpClientHandler在. 只要您不需要支持 Blazor,您就可以这样做: 

// clientless pattern:
FlurlHttp.Clients.WithDefaults(builder =>
    builder.UseSocketsHttpHandler(shh => {
        shh.PooledConnectionLifetime = TimeSpan.FromMinutes(10);
        ...
    }));

// DI pattern: 
services.AddSingleton<IFlurlClientCache>(_ => new FlurlClientCache()
    .WithDefaults(builder => builder.UseSocketsHttpHandler(shh => {
        ...
    })));

注意:在同一构建器上调用ConfigureInnerHandler和UseSocketsHttpHandler会导致运行时异常。使用其中之一,切勿同时使用。

Flurl 直接支持的最后一种消息处理程序类型是DelegatingHandler,这是一种可链接的处理程序类型,通常称为中间件,通常由第三方库实现。

// clientless pattern:
FlurlHttp.Clients.WithDefaults(builder => builder
    .AddMiddleare(new MyDelegatingHandler()));

// DI pattern: 
services.AddSingleton<IFlurlClientCache>(sp => new FlurlClientCache()
    .WithDefaults(builder => builder
        .AddMiddleware(sp.GetService<IMyDelegatingHandler>())

此示例使用流行的弹性库Polly以及在 DI 场景中配置 Flurl:

using Microsoft.Extensions.Http;

var policy = Policy
    .Handle<HttpRequestException>()
    ...

services.AddSingleton<IFlurlClientCache>(_ => new FlurlClientCache()
    .WithDefaults(builder => builder
        .AddMiddleware(() => new PolicyHttpMessageHandler(policy))));

 上面的示例需要安装Microsoft.Extensions.Http.Polly。

以上是配置相关的文档,我并没有在文档中发现关于https的相关配置。

Flurl.Http-3.2.4版本绕过https证书代码:

//Startup的ConfigureServices方法中配置
Flurl.Http.FlurlHttp.ConfigureClient(AppSettings.SFGZAPI.serversUrl, cli =>
                        cli.Settings.HttpClientFactory = new UntrustedCertClientFactory()); 


//此类建立你觉得方便的地方即可
public class UntrustedCertClientFactory : DefaultHttpClientFactory
{
    public override HttpMessageHandler CreateMessageHandler()
    {
        return new HttpClientHandler
        {
            ServerCertificateCustomValidationCallback = (a, b, c, d) => true
        };
    }
}

 对于4.0.0版本,经过一番阅读源代码【https://github.com/tmenier/Flurl】并测试,测试如下图:

上面截图代码均测试,依然还是:无法建立SSL连接。

又一次阅读文档无客户端使用,发现FlurlHttp.UseClientCachingStrategy说明:

看到可以在这个方法中设置FlurlHttp,一直以为是配置,原来我自己进入了坑,请阅读管理客户端相关文档:Managing Clients - Flurl 或阅读译文:.NetCore Flurl.Http 4.0.0 以上管理客户端-CSDN博客,于是开始了尝试并可以正常访问:

//无客户端使用
FlurlHttp.UseClientCachingStrategy(request =>
{
    FlurlHttp.Clients.GetOrAdd("https://xxx", "https://xxx", builder =>
    builder
    .ConfigureInnerHandler(hch =>
    {
        hch.ServerCertificateCustomValidationCallback = (a, b, c, d) => true;

    }));

    return "https://xxx";
});

测试:

/// <summary>
/// 无客户端模式
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("FlurlHttp")]
public async Task<ActionResult> FlurlHttp()
{
    try
    {
        var a = await "https://xxx"
        .WithHeader("xx", "xxx")
        .PostAsync()
        .ReceiveJson<dynamic>();

        return Ok(a);
    }
    catch (Exception ex)
    {
        return BadRequest(ex.Message);
    }
}

 还有依赖注入模式经过测试也是可以的:

希望本文对你有帮助。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/339852.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

js实现页面全屏展示

最近做一个网页项目&#xff0c;用户要求可以全屏展示&#xff0c;进入系统后隐藏地址栏&#xff0c;于是乎&#xff0c;经过调研就选择了全屏API&#xff0c;即便如此还是遇到了一些问题&#xff0c;总结一下&#xff0c;写下此篇文章。 全屏模式 获取Element节点&#xff0c…

红日靶场2打点记录

因为之前成功用冰蝎免杀360&#xff0c;把权限反弹到了MSF上&#xff0c;然后MSF把权限反弹到CS上 所以这次咱们走捷径直接通过反序列化漏洞连接&#xff08;就是关掉360&#xff09;因为权限弹来弹去感觉好麻烦 提示 大家如果想要免杀360千万别学我&#xff0c;我是之前免杀3…

【大数据分析与挖掘技术】Mahout推荐算法

目录 一、推荐的定义与评估 &#xff08;一&#xff09;推荐的定义 &#xff08;二&#xff09;推荐的评估 二、Mahout中的常见推荐算法 &#xff08;一&#xff09;基于用户的推荐算法 &#xff08;二&#xff09;基于物品的推荐算法 &#xff08;三&#xff09;基于S…

Linux配置主机名-使用主机名访问服务器

主要需要对Hosts文件进行操作&#xff0c; Hosts是一个没有扩展名的系统文件&#xff0c;可以用记事本等工具打开&#xff0c;其作用就是将一些常用的网址域名与其对应的IP地址建立一个关联“数据库”&#xff0c; 先将自己的主机名设置成有意义&#xff0c;别人好记的样子&a…

CTF-PWN-堆-【chunk extend/overlapping-1】

文章目录 chunk extend/overlappingfastbin与topchunk相邻free时候不会合并unsortedbinchunk中与topchunk相邻的被free时会合并extend向后overlapping先修改header&#xff0c;再free&#xff0c;再malloc先free&#xff0c;再修改header&#xff0c;再malloc extend向前overla…

【UEFI基础】EDK网络框架(TCP4)

TCP4 TCP4协议说明 相比UDP4&#xff0c;TCP4是一种面向连接的通信协议&#xff0c;因此有更好的可靠性。 TCP4的首部格式如下&#xff1a; 各个参数说明如下&#xff1a; 字段长度&#xff08;bit&#xff09;含义Source Port16源端口&#xff0c;标识哪个应用程序发送。D…

如何在 Ubuntu 22.04 上安装 Linux、Apache、MySQL、PHP (LAMP) 堆栈

前些天发现了一个人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;最重要的屌图甚多&#xff0c;忍不住分享一下给大家。点击跳转到网站。 如何在 Ubuntu 22.04 上安装 Linux、Apache、MySQL、PHP (LAMP) 堆栈 介绍 “LAMP”堆栈是一组开源软件&#…

Linux之进程管理篇(1)

初识进程 1.1 进程 进程&#xff1a;是具有独立功能的一次运行过程&#xff0c;是系统进行资源分配和调度的基本单位。Linux创建新进程时会为其指定和一个唯一的号码&#xff0c;即进程号(PID),以此区别不同的进程。进程不是程序&#xff08;程序&#xff1a;执行特定任务的一…

Istio

1、Istio介绍 Istio 是由 Google、IBM 和 Lyft 开源的微服务管理、保护和监控框架。 官网&#xff1a;https://istio.io/latest/zh/ 官方文档&#xff1a;https://istio.io/docs/ 中文官方文档&#xff1a;https://istio.io/zh/docs Github地址&#xff1a;https://github.com…

Kubernetes/k8s之包管理器helm

helm 在没有helm之前&#xff0c;我们要部署一个服务&#xff0c;deployment、service ingress 的作用通过打包的方式。把deployment、service ingress打包在一块&#xff0c;一键式部署服务。类似于yum功能。是官方提供的类似安装仓库的功能&#xff0c;可以实现一键化部署应…

Python量化交易- mplfinance库 -画K线图

mplfinance库 1. mplfinance 模块说明2. mplfinance安装3. mplfinance 模块 plot 基本用法参数typestylemake_addplot设置图表颜色 make_marketcolors添加图表样式 make_mpf_style 4. mplfinance 的基本K线图实现自定义风格和颜色图表尺寸调整、相关信息的显示添加完整移动平均…

C语言爬虫程序编写的爬取APP通用模板

互联网的飞快发展&#xff0c;尤其是手机终端业务的发展&#xff0c;让越来越多的事情都能通过手机来完成&#xff0c;电脑大部分的功能也都能通过手机实现&#xff0c;今天我就用C语言写一个手机APP类爬虫教程&#xff0c;方便后期拓展APP爬虫业务。而且这个模板是通用的适合各…

SIP12 脚模块式单路交流信号隔离变送器0~1VAC/0~5VAC转4-20mA/0-5VDC

概述&#xff1a; IPO AC系列模块式交流电压隔离变送器&#xff0c;能将输入的交流信号按比例转换成4~20mA标准信号, 输入为0~1Vrms等交流电压信号&#xff1b;输出为4~20mA直流电流信号或0~5VDC直流电压信号。实现辅助电源和输入输出信号之间2500VDC隔离&#xff0c;输入信号…

DevOps系列文章之 GitLab CI/CD

CICD是什么? 由于目前公司使用的gitlab&#xff0c;大部分项目使用的CICD是gitlab的CICD&#xff0c;少部分用的是jenkins&#xff0c;使用了gitlab-ci一段时间后感觉还不错&#xff0c;因此总结一下 介绍gitlab的CICD之前&#xff0c;可以先了解CICD是什么 我们的开发模式…

力扣刷MySQL-第五弹(详细讲解)

&#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;力扣刷题讲解-MySQL &#x1f379;文章作者技术和水平很有限&#xff0c;如果文中出…

超级菜鸟怎么学习数据分析?

如果你有python入门基础&#xff0c;在考虑数据分析岗&#xff0c;这篇文章将带你了解&#xff1a;数据分析人才的薪资水平&#xff0c;数据人应该掌握的技术栈。 首先来看看&#xff0c;我在搜索数据分析招聘时&#xff0c;各大厂开出的薪资&#xff1a; 那各大厂在数据领域…

【Spring 篇】MyBatis多表操作:编织数据的交响乐

欢迎来到MyBatis的多表操作世界&#xff01;在这个充满交响乐的舞台上&#xff0c;我们将探索如何巧妙地编织多个数据表的数据&#xff0c;创造出一场旋律动听的数据交响曲。无需繁琐的SQL拼接&#xff0c;MyBatis让多表操作变得优雅而简单。让我们一起进入这个音乐殿堂&#x…

二.Winform使用Webview2在Demo1中实现地址简单校验

Winform使用Webview2在Demo1中实现地址简单校验 往期目录回顾添加对于的简单url验证提示通过上节和本节涉及到的函数有 往期目录 往期相关文章目录 专栏目录 回顾 通过一.Winform使用Webview2(Edge浏览器核心) 创建demo(Demo1)实现回车导航到指定地址 我们已经知道了解决资源…

裁员背景下 | 【2024年人生的里程碑】作为独立开发者,第一次承接外包项目的心得经历,也许说出你的心声哦!

&#x1f6aa; 每日一句 种子不落在肥土而落在瓦砾中&#xff0c;有生命力的种子决不会悲观和叹气&#xff0c;因为有了阻力才有磨炼。 背景介绍 在裁员背景下&#xff0c;寻找自主承包项目成为了一种可行且具有吸引力的选择。对于职业技术人员而言&#xff0c;自主承包项目不…

【服务器】Xshell与Xftp软件的使用指南

目录 【Xshell软件】 1.1 Xshell软件的功能 1.2 Xshell软件的使用 【Xftp软件】 2.1 Xftp软件的功能 2.2 Xftp软件的使用 可替代产品【FinalShell】 3.1 FinalShell软件的使用 3.2 FinalShell连接服务器失败解决方法 可替代产品【FileZilla】
最新文章