当尝试在Xamarin.Forms Android上访问服务器时,抛出System.AggregateException异常。

4

我使用HttpClient与服务器进行通信,如下所示:

private static readonly HttpClientHandler Handler = new HttpClientHandler
                                                                 {
                                                                     AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip,
                                                                     AllowAutoRedirect      = true,
                                                                 };
    
private static readonly HttpClient Client = new HttpClient(Handler, false);

问题是在安卓上出现了System.AggregateException异常。 异常细节可以在下面的截图中看到: Exception Screenshot

这个应用在iOS上运行得非常好。

服务器正在使用 Let's Encrypt 证书,自从一周前更新证书以来,问题才浮出水面。

我已经检查了与证书有效性(到期、DNS名称等)有关的所有内容,都看起来没有问题。


重要的部分在突出显示的“InnerException”下面的“Message”属性中:以“Ssl error: 1000007d”开头的那个。你能把整个内容都贴出来吗? - canton7
1
通过应用您的响应中的见解,整个情况得到了纠正。我最终在服务器上编辑了 fullchain.pem,但我想您的建议1是最优雅的。我会尝试并更新。 - Ali
1个回答

2
这是 Xamarin.Android 中一个长期存在的问题#6351,由于 LetsEncrypt 的根证书过期并移动到新的根证书而引起。
以下是我在该问题中发布的帖子的副本,解释了情况和解决方法。请查看该线程中其他帖子以获取有关解决方法的详细信息。
Scott Helme有一篇非常棒的文章介绍了这种情况。先去读一下那篇文章,然后我会描述一下(我认为)这如何适用于xamarin-android。
我将复制该文章的关键图表(来源):

image

红色链是过去的情况:IdenTrust DST Root CA X3是一张旧的根证书,几乎被所有地方信任,包括Android 2.3.6及以后的设备。这就是LetsEncrypt曾经使用的根证书,这意味着每个人都信任他们。然而,IdenTrust DST Root CA X3最近已经过期,这意味着一些设备不会信任任何由它签名的东西。LetsEncrypt需要转向他们自己的根证书。
蓝色链是理想的新链 -- ISRG Root X1是LetsEncrypt自己的根证书,它包含在Android 7.1.1+中。Android版本>= 7.1.1将信任由ISRG Root X1签署的证书。
然而,问题是旧的Pre-7.1.1 Android设备不知道ISRG Root X1,并且不信任它。

LetsEncrypt正在使用的解决方法是,旧的Android设备不检查根证书是否已过期。因此,默认情况下提供一个包括LetsEncrypt的根ISRG Root X1证书(更新的设备信任)的链,但也包括那个现在已过期的IdenTrust DST Root CA X3的签名。这意味着旧的Android设备信任该链(因为它们信任IdenTrust DST Root CA X3,并且不检查它是否过期),而较新的设备也信任该链(因为它们能够计算出即使链的根已过期,它们仍然信任那个中间的ISRG Root X1证书作为有效的根,因此信任它)。

这是绿色路径,这是LetsEncrypt目前默认提供的路径。

然而,xamarin-android使用的BoringSSL库不是Android的SSL库。它1)不信任IdenTrust DST Root CA X3,因为它已过期,2)不能聪明地弄清楚它确实信任也在该链中的ISRG Root X1。因此,如果您提供上面图片中的绿色链,则它无法信任它。

因此,选择有:

  1. 不要使用BoringSSL,而是使用Android的SSL库。这意味着xamarin-android的行为与其他Android应用程序相同,并信任过期的根证书。这是通过使用前面描述的AndroidClientHandler实现的。这应该可以解决Android >= 2.3.6的问题。
  2. 使用BoringSSL,但从Android的信任存储中删除过期的IdenTrust DST Root CA X3(在设置中为“Digital Signature Trust Co. - DST Root CA X3”)。这会欺骗BoringSSL停止其链在ISRG Root X1处,它信任(在Android 7.1.1+上)。然而,这仅适用于信任ISRG Root X1的Android设备,即7.1.1+。
  3. 使用BoringSSL,并将服务器更改为提供以ISRG Root X1为根的链,而不是过期的IdenTrust DST Root CA X3(上图中的蓝色链),使用--preferred-chain“ISRG Root X1”。这意味着BoringSSL完全忽略IdenTrust DST Root CA X3,并将根源于ISRG Root X1。这同样只适用于信任ISRG Root X1的Android设备,即7.1.1+。
  4. 与3相同,但通过手动编辑fullchain.pem实现。
  5. 使用另一个CA,例如ZeroSSL,它使用一个根证书,该根证书被信任返回到Android 2.2,并且直到2038年才过期。

很好,非常详细!谢谢。但是还有一个模糊的问题困扰着我。
  • 如果我没记错的话,根CA证书在9月左右过期了。在那之后,我已经更新了我的证书一次,直到几天前都一直工作正常。这里似乎有些东西丢失了,不是吗?
另外,关于你的第一个建议,人们可以查看此GitHub要点。
- Ali
有趣。我不确定如何解释这个问题——也许BoringSSL实际上是因为根证书在订阅者证书的“Not Before”日期之前过期而出现了问题?这符合数据,但这是一个稍微奇怪的检查。 - canton7
实际上,仔细考虑,检查订阅证书有效时根是否有效是一个明智的检查,这符合数据,所以这可能就是发生的情况。您的旧订阅证书之所以有效,是因为签署它的时候根有效的。 - canton7

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接