Https网络请求,dio库不走badCertificateCallback回调

来源:1-2 课程导学

慕设计5218244

2024-07-23

1、我使用了dio库,并全局设置了如下代码,进行Https请求,但是不走badCertificateCallback回调,是什么原因?
2、上线的时候需要在badCertificateCallback中判断pem是否正确吗?

      HttpOverrides.global = ProxiedHttpOverridesDebug("");

class ProxiedHttpOverridesDebug extends HttpOverrides {
  String _proxy;

  ProxiedHttpOverridesDebug(this._proxy);

  @override
  HttpClient createHttpClient(SecurityContext? context) {
    return super.createHttpClient(context)
      ..findProxy = (uri) {
        return _proxy.isNotEmpty ? "PROXY $_proxy;" : 'DIRECT';
      }
      ..badCertificateCallback = (X509Certificate cert, String host, int port) {
        if (cert.pem == ThingsboardAppConstants.X509CertificatePem) {
          return true;
        }
        return false;
      };
  }
}

写回答

1回答

CrazyCodeBoy

2024-07-24

在使用 Dio 库进行 HTTPS 请求时,如果你发现 `badCertificateCallback` 回调没有被调用,可能有以下几个原因:

1. **证书有效**:如果你请求的服务器证书是有效的,并且被系统信任的 CA 签署,那么 `badCertificateCallback` 就不会被触发。

2. **请求未到达 HTTPS 证书验证**:如果请求在到达证书验证之前就失败(例如由于网络问题或 DNS 解析错误),则 `badCertificateCallback` 也不会被触发。

3. **设置不正确**:确保你正确设置了 `badCertificateCallback`,并且它确实应用于你的 Dio 实例。

以下是一个正确设置 `badCertificateCallback` 的示例:

```dart
import 'package:dio/dio.dart';

void main() {
  final dio = Dio();

  (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) {
    client.badCertificateCallback = (X509Certificate cert, String host, int port) {
      // 在这里处理证书验证
      return true; // 始终接受证书(上线时需要更严格的验证)
    };
  };

  // 进行 HTTPS 请求
  dio.get('https://example.com').then((response) {
    print(response.data);
  }).catchError((error) {
    print(error);
  });
}
```

### 关于上线时的证书验证

在生产环境中,绝对不建议简单地返回 `true` 来跳过证书验证。你应该严格验证证书,以防止中间人攻击等安全问题。以下是一些建议:

1. **校验证书的 PEM**:
   在 `badCertificateCallback` 中,对比证书的 PEM 内容是否与预期的一致。

2. **使用安全的 CA**:
   确保你的服务器证书是由受信任的 CA 签署的,这样可以避免需要手动验证证书。

3. **定期更新证书**:
   确保你定期更新证书,避免证书过期导致请求失败。

示例如下:

```dart
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:flutter/services.dart';
import 'package:http/io_client.dart';
import 'package:http/http.dart' as http;
import 'package:http_client_helper/http_client_helper.dart';

void main() async {
  final dio = Dio();

  // 读取你的证书 PEM 内容
  final pem = await rootBundle.loadString('assets/your_cert.pem');

  (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) {
    final SecurityContext context = SecurityContext();
    context.setTrustedCertificatesBytes(utf8.encode(pem));

    return HttpClient(context: context)
      ..badCertificateCallback = (X509Certificate cert, String host, int port) {
        // 检查证书是否匹配
        return cert.pem == pem;
      };
  };

  // 进行 HTTPS 请求
  dio.get('https://example.com').then((response) {
    print(response.data);
  }).catchError((error) {
    print(error);
  });
}
```

通过这种方式,你可以确保上线时对证书进行严格的校验,保证请求的安全性。
1
0

Flutter高级进阶实战-仿哔哩哔哩-掌握Flutter高阶技能

一次性掌握Flutter高阶技能+商业级复杂项目架构设计与开发方案

1723 学习 · 870 问题

查看课程