Flutter应用调用Docker API时如何使用三类SSL/TLS证书发送请求
Flutter调用带SSL/TLS双向认证的Docker Engine API解决方案
前置准备
- 将
ca.pem、cert.pem、key.pem三个凭证文件放入项目的assets目录下 - 在
pubspec.yaml中声明资源依赖:
flutter: assets: - assets/ca.pem - assets/cert.pem - assets/key.pem
- 安装dio依赖,执行命令:
flutter pub add dio
核心实现代码
核心思路是通过Dart原生的SecurityContext加载三类凭证,再将自定义的安全上下文绑定到请求客户端中,完整示例如下:
import 'dart:io'; import 'package:dio/dio.dart'; import 'package:flutter/services.dart'; class DockerApiClient { late Dio _dio; final String baseUrl = "https://65.0.95.227:2376"; // 初始化客户端,加载凭证 Future<void> init() async { // 读取assets中的三个凭证文件为字节 final caCert = await rootBundle.load('assets/ca.pem'); final clientCert = await rootBundle.load('assets/cert.pem'); final clientKey = await rootBundle.load('assets/key.pem'); // 创建自定义安全上下文 SecurityContext securityContext = SecurityContext(); // 加载CA根证书,对应curl的--cacert参数/requests的verify参数 securityContext.setTrustedCertificatesBytes(caCert.buffer.asUint8List()); // 加载客户端证书,对应curl的--cert参数/requests的cert第一个参数 securityContext.useCertificateChainBytes(clientCert.buffer.asUint8List()); // 加载客户端私钥,对应curl的--key参数/requests的cert第二个参数 // 如果私钥设置了密码,需要传入password参数 securityContext.usePrivateKeyBytes(clientKey.buffer.asUint8List()/*, password: "你的私钥密码"*/); // 自定义HttpClient HttpClient httpClient = HttpClient(context: securityContext); // 如果是用IP访问、证书与域名不匹配,可以放开下面的配置自定义校验逻辑,生产环境不建议直接禁用校验 // httpClient.badCertificateCallback = (X509Certificate cert, String host, int port) { // return host == '65.0.95.227'; // 仅允许指定IP的证书 // }; // 将自定义HttpClient绑定到Dio _dio = Dio(BaseOptions(baseUrl: baseUrl)); (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = () { return httpClient; }; } // 获取容器列表示例,对应Python示例的接口 Future<List<dynamic>> getContainerList() async { Response response = await _dio.get('/containers/json', queryParameters: {'all': 1}); return response.data; } // 打印容器信息示例 Future<void> printContainersData() async { List containers = await getContainerList(); for (var container in containers) { print('Container [Id: ${container['Id']}, Name: ${container['Names'][0]}, Status: ${container['Status']}]'); } } } // 调用示例 void main() async { DockerApiClient client = DockerApiClient(); await client.init(); await client.printContainersData(); }
注意事项
- 上述方案仅适用于测试环境,生产环境请勿将凭证文件打包在APP assets中,避免凭证泄露,建议通过用户手动上传、服务端动态下发加密存储的方式获取凭证
- 若使用http包而非dio,逻辑完全一致,直接将自定义
SecurityContext传入HttpClient构造方法即可使用 - 私钥如果有加密,需要在调用
usePrivateKeyBytes时传入对应的password参数
内容的提问来源于stack exchange,提问作者mtabishk
相关产品推荐
相关产品推荐

