Flutter Dio HTTPS 证书验证忽略 onBadCertificate - CA 证书问题?
Flutter Dio HTTPS Certificate Validation Ignoring onBadCertificate - CA Cert Problem?
我 运行 有点进退两难。我正在编写 client/server 应用程序。前端在 Flutter 中,使用 Dio http 包,后端是 Java。后端 REST API 通过 TLS 证书进行保护。
正如许多其他问题指出的那样,Flutter 似乎无法访问所有平台上的系统 CA 证书存储。这是有问题的,因为我打算允许服务器应用程序的自托管,这意味着可以在服务器端使用来自所有不同 CA 的证书,因此我的 HTTP 客户端将需要支持典型 Web 浏览器支持的所有 CA。
Dio 显然允许您设置受信任的证书链,但我想知道如何最好地利用它。
有没有人遇到过这个问题。您实施了什么解决方案来解决这个问题?
这些是我目前想到的解决方案:
- 允许用户“上传”ca 证书包并在 shared_preferences 中存储字节(用户很难)
- 寻找另一种方法来验证证书,例如用户输入指纹? (难度较低,让所有证书都无法通过原始验证,然后使用 onBadCertificate 对存储的指纹进行自定义验证)
- 查找提供对系统证书存储的访问权限的软件包
- 在应用程序中运送大部分知名 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 证书存储。当我测试其他平台时,如果我 运行 遇到任何证书问题,我会更新。但是这个已经解决了!
最终的核心问题是服务器没有提供完整的证书链,只提供了叶证书。如果浏览器在其他地方看到了中间证书,则某些浏览器会隐藏此类问题。因此,仅仅因为浏览器中的一切正常,并不意味着服务器实际上为其他 TLS 客户端提供了足够的信息来验证证书链。
因此,解决方案是配置服务器以提供完整的证书链。
我也有同样的问题,因为在一些旧型号的手机上,用户看到证书错误。所以,我找到了这个解决方案:
_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
我 运行 有点进退两难。我正在编写 client/server 应用程序。前端在 Flutter 中,使用 Dio http 包,后端是 Java。后端 REST API 通过 TLS 证书进行保护。
正如许多其他问题指出的那样,Flutter 似乎无法访问所有平台上的系统 CA 证书存储。这是有问题的,因为我打算允许服务器应用程序的自托管,这意味着可以在服务器端使用来自所有不同 CA 的证书,因此我的 HTTP 客户端将需要支持典型 Web 浏览器支持的所有 CA。
Dio 显然允许您设置受信任的证书链,但我想知道如何最好地利用它。
有没有人遇到过这个问题。您实施了什么解决方案来解决这个问题?
这些是我目前想到的解决方案:
- 允许用户“上传”ca 证书包并在 shared_preferences 中存储字节(用户很难)
- 寻找另一种方法来验证证书,例如用户输入指纹? (难度较低,让所有证书都无法通过原始验证,然后使用 onBadCertificate 对存储的指纹进行自定义验证)
- 查找提供对系统证书存储的访问权限的软件包
- 在应用程序中运送大部分知名 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 证书存储。当我测试其他平台时,如果我 运行 遇到任何证书问题,我会更新。但是这个已经解决了!
最终的核心问题是服务器没有提供完整的证书链,只提供了叶证书。如果浏览器在其他地方看到了中间证书,则某些浏览器会隐藏此类问题。因此,仅仅因为浏览器中的一切正常,并不意味着服务器实际上为其他 TLS 客户端提供了足够的信息来验证证书链。
因此,解决方案是配置服务器以提供完整的证书链。
我也有同样的问题,因为在一些旧型号的手机上,用户看到证书错误。所以,我找到了这个解决方案:
_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