You need to enable JavaScript to run this app. Flutter 如何为http包请求添加证书校验以实现SSL HTTPS连接
优惠活动
大模型
产品
解决方案
定价
更多

Flutter 如何为http包请求添加证书校验以实现SSL HTTPS连接

Dart http包实现HTTPS证书校验的落地方案

核心实现逻辑

http包本身不直接在请求对象层提供证书校验的挂载入口,所有HTTPS证书校验逻辑都绑定在底层TCP连接建立阶段,需要通过自定义可复用的Client实例注入校验规则,不能直接在MultipartRequest的代码块位置插入校验逻辑。
常见的证书校验场景分为两类:

  • 服务端使用公共可信CA签发的证书:系统会默认完成完整的证书链校验、域名匹配、有效期校验,不需要额外编写自定义代码即可正常建立加密连接
  • 服务端使用自签证书、或需要通过证书钉扎提升安全性的场景:需要将服务端证书打包进应用安装包,通过自定义安全上下文、证书校验回调实现强校验

适配现有业务代码的改造步骤

  1. 提前将服务端的PEM格式证书文件放置到项目的assets/certs/目录下,在pubspec.yaml中完成assets路径声明
  2. 封装带证书校验逻辑的自定义Client实例,替换默认的直连客户端
  3. 发送Multipart请求时,将自定义Client实例传入请求发送方法,确保请求走带校验逻辑的连接通道

参考实现代码

首先封装带校验逻辑的客户端初始化方法:

import 'dart:io';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:http/io_client.dart';

Future<http.Client> initSecureHttpsClient() async {
  // 加载应用内置的服务端证书到系统安全上下文
  final serverCertBytes = await File('assets/certs/mywebsite_server.crt').readAsBytes();
  final secureContext = SecurityContext.defaultContext
    ..setTrustedCertificatesBytes(serverCertBytes);

  // 配置底层HttpClient的证书校验回调
  final rawHttpClient = HttpClient(context: secureContext)
    ..badCertificateCallback = (X509Certificate cert, String host, int port) {
      // 自定义校验规则:匹配目标域名、校验证书主体信息
      final isTargetHost = host == 'www.mywebsite.com';
      final isCertMatch = cert.subject.contains('O=MyWebsite Inc');
      // 所有校验条件满足才放行连接
      return isTargetHost && isCertMatch;
    };

  // 将底层HttpClient包装为http包可识别的Client实例
  return IOClient(rawHttpClient);
}

替换原有请求逻辑,接入自定义带校验的客户端:

Future<void> sendLookupRequest() async {
  String url = "https://www.mywebsite.com";
  print("Firing off url: ${url}");

  // 初始化带证书校验的客户端
  final secureClient = await initSecureHttpsClient();
  var request = http.MultipartRequest("POST", Uri.parse(url));

  // 保留原有POST字段逻辑
  request.fields["lookup"] = "true";
  request.fields["email"] = "blah@test.com";
  request.fields["user_id"] = "1337";

  // 传入自定义客户端发送请求
  var response = await request.send(secureClient);
  var responseData = await response.stream.toBytes();
  var responseString = String.fromCharCodes(responseData);

  print('================================');
  print("response was: ${responseString}");
  if (response.statusCode == 200) {
    var json_data = json.decode(responseString);
    for (var u in json_data) {
      print(u["response"]);
    }
  }

  // 请求完成后释放客户端连接资源
  secureClient.close();
}

关键注意事项

  • 严禁在badCertificateCallback中直接写死返回true,该写法会完全跳过所有HTTPS安全校验,存在被中间人攻击窃取明文数据的重大风险
  • 证书校验逻辑建议补充证书公钥指纹的比对,仅靠域名匹配的校验无法完全防范CA被篡改带来的安全风险
  • 如果服务端使用公共可信CA签发的证书,不需要手动加载自定义证书文件,仅在回调中补充必要的指纹校验即可

内容的提问来源于stack exchange,提问作者Petro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.06 07:36:03