Flutter Dio HTTPS证书验证忽略onBadCertificate - CA证书问题?

3
我遇到了一个困境。我正在编写一个客户端/服务器应用程序。前端使用Flutter和Dio http包,后端是Java。后端REST API使用TLS证书进行安全保护。
正如许多其他问题所指出的那样,Flutter在所有平台上似乎都没有访问系统CA证书存储的权限。这是个问题,因为我打算允许服务器应用程序进行自托管,这意味着可以使用来自各种CA的证书,因此我的HTTP客户端需要支持Typical Web Browser支持的所有CA。
Dio显然允许您设置受信任的证书链,但我想知道如何最好地利用它。
有人以前遇到过这个问题吗?你实施了什么解决方案?
我目前想到的解决方案如下:
1. 允许用户“上传”ca证书包并将字节存储在shared_preferences中(对用户来说很难)
2. 找到另一种验证证书的方法,例如使用用户输入的指纹?(不太难,让所有证书无法通过原始验证,然后使用存储的拇指印针对onBadCertificate进行自定义验证)
3. 找到一个提供访问系统证书存储库的软件包
4. 在应用程序内部发布大量知名CA证书,并以某种方式使用Dio信任它们
我提出的另一个问题是,Dio似乎忽略了我的onBadCertificate方法。我在ConnectionManager中声明了这个方法,是否不应该这样做?
以下是被忽略的代码:
var dio = Dio()
  ..options.baseUrl = server
  ..interceptors.add(LogInterceptor())
  ..interceptors.add(CookieManager(cookieJar))
  ..httpClientAdapter = Http2Adapter(
    ConnectionManager(
      idleTimeout: 10000,
      // Ignore bad certificate
      onClientCreate: (_, config) => {
        //config.context?.setTrustedCertificatesBytes(File("/assets/certs/wildcard.pem").readAsBytesSync()),
        config.onBadCertificate = (_) => true, // <-- ignored, should bypass check
      }
    ),
  );

编辑:

如评论中所述,Flutter 实际上能够使用系统的 CA 证书库。如果我在测试其他平台时遇到证书问题,我会进行更新。但这个问题已经解决了!


1
Flutter 在所有平台上似乎没有访问系统 CA 证书存储的权限,这可能是正确的,但在这些平台上,Flutter 配备了自己的信任存储库,其中包含与 Mozilla 几乎相同数量的 CA。因此,您确定您确实有问题吗?您是否知道某个 CA 不受支持,而 Flutter 应该支持它? - julemand101
我正在使用从Entrust直接购买的证书。Dio无法在Android上验证该证书,但在Windows上运行良好。 - TheFunk
1
安卓的哪个版本?手机中的CA是否在信任商店中? - julemand101
1
另外,可能有很多其他的问题。例如,如果您的服务器没有发送中间证书。如果浏览器可以根据历史数据猜测根证书,则某些浏览器将忽略此问题。因此,配置不良的服务器可能会保持隐藏。 - julemand101
1
那么,这个问题的状态如何?你找到解决方案了吗?还是您需要帮助找到核心问题? :) - julemand101
显示剩余5条评论
2个回答

4

我也遇到了同样的问题,因为在一些旧型号的手机上,用户会看到证书错误。所以,我找到了这个解决方案:

_dio = Dio(_baseOptions);

    //check bad certificate
    (_dio!.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (HttpClient client) {
      client.badCertificateCallback = (X509Certificate cert, String host, int port) => true;
      return client;
    };

https://github.com/flutterchina/dio/issues/32#issuecomment-487401443


1
核心问题最终是服务器没有提供完整的证书链,而只提供了叶子证书。如果浏览器在其他地方看到了中间证书,那么它会隐藏这种问题。因此,仅仅因为浏览器可以正常工作,并不意味着服务器实际上提供了足够的信息供其他TLS客户端验证证书链。
解决方案是配置服务器提供完整的证书链。

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