尝试使用NetworkImage加载图像失败,并且没有证书

时间:2018-04-16 08:41:10

标签: flutter

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

是否有针对此的解决方法,类似于HTTPClient中的操作方式? httpClient.badCertificateCallback =(X509Certificate cert,String host,int port)=>真;

5 个答案:

答案 0 :(得分:2)

是的,有一个简单的解决方案。只需将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)

答案 1 :(得分:1)

这是给以后出现在这里的人的。我只是用@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) {
    return new MultiFrameImageStreamCompleter(
        codec: _loadAsync(key),
        scale: key.scale,
        informationCollector: (StringBuffer information) {
          information.writeln('Image provider: $this');
          information.write('Image key: $key');
        });
  }

  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)';
}

答案 2 :(得分:0)

在_network_image_io.dart文件中 找到

  static HttpClient get _httpClient {
HttpClient client = _sharedHttpClient;
assert(() {
  if (debugNetworkImageHttpClientProvider != null)
    client = debugNetworkImageHttpClientProvider();
  return true;
}());
return client;}

并将其更改为

  static HttpClient get _httpClient {
HttpClient client = _sharedHttpClient
  ..badCertificateCallback =
  ((X509Certificate cert, String host, int port) => true);
assert(() {
  if (debugNetworkImageHttpClientProvider != null)
    client = debugNetworkImageHttpClientProvider();
  return true;
}());
return client;}

答案 3 :(得分:0)

如果上述代码导致安全错误,请在“ _network_image_io.dart”中尝试

    static HttpClient get _httpClient {
    HttpClient client = _sharedHttpClient
      ..badCertificateCallback =
          ((X509Certificate cert, String host, int port) => true);
    assert(() {
      if (debugNetworkImageHttpClientProvider != null)
        client = debugNetworkImageHttpClientProvider!();//only change is "!()"
      return true;
    }());
    return client;
  }

答案 4 :(得分:0)

取自here

class MyHttpOverrides extends HttpOverrides{
  @override
  HttpClient createHttpClient(SecurityContext context){
    return super.createHttpClient(context)
      ..badCertificateCallback = (X509Certificate cert, String host, int port)=> true;
  }
}

void main(){
    HttpOverrides.global = new MyHttpOverrides();
    runApp(new MyApp());
}