Dio https 请求中出现 Flutter 错误。 HandshakeException:客户端操作系统中出现握手错误错误:(TLSV1_ALERT_DECODE_ERROR(tls_record.cc:594))

问题描述 投票:0回答:3

我正在尝试使用以下功能从 flutter 发送

https
请求:

Future<void> sendOTP(PhoneNumber phoneNumber) async {
    try {
      final String url = 'https://127.0.0.1:5432/api/send_otp';

      final response = await _dio.post(
        url,
        data: {'number': 1234567890},
        options: Options(
          headers: {
            'Content-Type': 'application/json',
          },
        ),
      );

      if (response.statusCode != 200) {
        throw Exception("Failed to send OTP: ${response.statusCode}");
      }
    } on DioError catch (e) {
      throw Exception("Failed to send OTP: ${e.error.toString()}");
    }
  }

要启用

ssl certificate
,我在我的主要方法中添加了以下代码:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  ByteData data = await PlatformAssetBundle().load('asset/certificate/certificate.pem');
  SecurityContext.defaultContext
      .setTrustedCertificatesBytes(data.buffer.asUint8List());
  runApp(const MyApp());
}

我已经从

https://letsencrypt.org/certs/lets-encrypt-r3.pem
下载了 certificate.pem 文件。

当我使用

thunderclient
postman
和证书发送请求时,它可以工作,但从 flutter 应用程序中它会抛出以下错误:

Error: HandshakeException: Handshake error in client (OS Error:
    TLSV1_ALERT_DECODE_ERROR(tls_record.cc:594))

对于服务器,我使用

actix-web
rustls
- 如果相关的话。请建议我该如何解决这个问题?

flutter ssl https dio
3个回答
0
投票

我有类似的问题,经过几个小时的研究我发现:

  • 如果您有默认配置的 Android 模拟器,您必须能够通过以下 IP 地址从模拟器浏览器访问您的 url:https://10.0.2.2:[portNumber]/api。根据文档,这是您的本地主机(您的计算机)的别名。
  • 我更改了我的 asp.net api 配置以在本地计算机 Wi-Fi IP 地址中进行响应,在我的例子中是 192.168.100.2,如下图所示: enter image description here

如您所见,我的 API 是通过 android 模拟器访问的,但如果我使用 Dio Http(版本 5.1.1)运行我的 flutter 代码,它会抛出握手异常。 我尝试了与您使用的完全相同的代码,添加了证书但没有任何改变。我真的不知道从现在开始该怎么办。这真的很令人沮丧,也许我必须使用 Brownser 而不是模拟器来开发我的应用程序。

这是我的 dio 基本选项配置,没问题:

enter image description here

这是 Dio Http 抛出的异常: enter image description here

我还尝试在 android 清单中添加互联网权限,但没有任何改变,我还尝试指向我的 API 的 http 版本,但发生了相同的错误。 也许这是 Dio Http 的一个 bug?


0
投票

经过一番研究,我终于找到了这个问题的解决方案。基本上你必须在创建 Dio 实例时添加以下代码:

class DioSingleton {
  static final baseOptions = BaseOptions(
    baseUrl: "https://10.0.2.2:7027/api/",
  );

  static Dio createInstance() {
    var dio = Dio(baseOptions);
    dio.httpClientAdapter = IOHttpClientAdapter(
      onHttpClientCreate: (client) {
        client.badCertificateCallback =
            (X509Certificate cert, String host, int port) => true;
        return client;
      },
    );
    return dio;
  }
}

此外,您不需要配置 Android 模拟器来使用代理或任何不同的配置。只需“按原样”使用,一切都会正常。 如果您的计算机上运行着 localhost api,请记住使用地址 10.0.2.2。就我而言,我有一个在本地主机中运行的 .net6 API。 如果这解决了您的问题,请将此标记为接受的答案。


0
投票

试试这个:

 final Dio client;
 final Duration _defaultTimeout = const Duration(seconds: 25);

 ConfiguredDio({required this.client}) {
 client.httpClientAdapter = IOHttpClientAdapter(
    createHttpClient: () => HttpClient()..badCertificateCallback = (_, __, ___) => true);
© www.soinside.com 2019 - 2024. All rights reserved.