对于没有证书的 HTTPS 站点,尝试使用 NetworkImage 加载图像失败并显示 CERTIFICATE_VERIFY_FAILED

use*_*845 5 flutter

在 Flutter 中,尝试使用NetworkImage从(开发)服务器(没有证书的 HTTPS)加载图像- 导致抛出异常:客户端中的握手错误(操作系统错误:CERTIFICATE_VERIFY_FAILED:ok(handshake.cc:355))

是否有解决方法,类似于它在HTTPClient 中的完成方式?httpClient.badCertificateCallback = (X509Certificate cert, String host, int port) => true;

Ind*_*tta 5

这是为后来出现在这里的人准备的。我只是帮助其他人使用@Alexey 所说的 NetworkImageSSL 的完整代码(他给出的优秀解决方案)。

import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'dart:ui' as ui show instantiateImageCodec, Codec;

import 'package:flutter/foundation.dart';
import 'package:flutter/painting.dart';

class NetworkImageSSL extends ImageProvider<NetworkImageSSL> {
  const NetworkImageSSL(this.url, {this.scale = 1.0, this.headers})
      : assert(url != null),
        assert(scale != null);

  final String url;

  final double scale;

  final Map<String, String> headers;

  @override
  Future<NetworkImageSSL> obtainKey(ImageConfiguration configuration) {
    return new SynchronousFuture<NetworkImageSSL>(this);
  }

  @override
  ImageStreamCompleter load(NetworkImageSSL key, DecoderCallback decode) {
    return MultiFrameImageStreamCompleter(codec: _loadAsync(key), scale: key.scale);
  }

  static final HttpClient _httpClient = new HttpClient()
    ..badCertificateCallback =
        ((X509Certificate cert, String host, int port) => true);

  Future<ui.Codec> _loadAsync(NetworkImageSSL key) async {
    assert(key == this);

    final Uri resolved = Uri.base.resolve(key.url);
    final HttpClientRequest request = await _httpClient.getUrl(resolved);
    headers?.forEach((String name, String value) {
      request.headers.add(name, value);
    });
    final HttpClientResponse response = await request.close();
    if (response.statusCode != HttpStatus.ok)
      throw new Exception(
          'HTTP request failed, statusCode: ${response?.statusCode}, $resolved');

    final Uint8List bytes = await consolidateHttpClientResponseBytes(response);
    if (bytes.lengthInBytes == 0)
      throw new Exception('NetworkImageSSL is an empty file: $resolved');

    return await ui.instantiateImageCodec(bytes);
  }

  @override
  bool operator ==(dynamic other) {
    if (other.runtimeType != runtimeType) return false;
    final NetworkImageSSL typedOther = other;
    return url == typedOther.url && scale == typedOther.scale;
  }

  @override
  int get hashCode => hashValues(url, scale);

  @override
  String toString() => '$runtimeType("$url", scale: $scale)';
}
Run Code Online (Sandbox Code Playgroud)

  • @Osman如果你在Master分支上那么你需要改变这个方法。我也遇到过这个问题。我当前的代码是: `@override ImageStreamCompleter load(NetworkImageSSL key) { return new MultiFrameImageStreamCompleter( codec: _loadAsync(key), scale: key.scale); }` (2认同)

Ale*_*xey 4

是的,有一个简单的解决方案。只需将源代码复制并粘贴class NetworkImage到您的代码库中,然后修改它以接受任何 SSL。

它位于/flutter/packages/flutter/lib/src/painting/image_provider.dart

将其重命名为类似名称NetworkImageSSL以避免与原始类发生名称冲突。那么,在这堂课中你会发现

static final HttpClient _httpClient = new HttpClient();

将其替换为

static final HttpClient _httpClient = new HttpClient() ..badCertificateCallback = ((X509Certificate cert, String host, int port) => true);

在编译之前包含必要的包(您可以从 复制相关导入image_provider.dart)。现在您可以按如下方式加载图像:

new Image(image: NetworkImageSSL(thumbURL), fit: BoxFit.cover)