如何解决执行POST请求时出现的CERTIFICATE_VERIFY_FAILED错误?

时间:2019-01-21 07:25:59

标签: dart flutter

我正在Dart中发送发帖请求。当我在Postman等API测试工具上进行测试时,它会给出响应。但是当我运行该应用程序时。它给了我以下错误:-

E/flutter ( 6264): HandshakeException: Handshake error in client (OS Error: E/flutter ( 6264):  CERTIFICATE_VERIFY_FAILED: unable to get local issuer certificate(handshake.cc:363))

这是我的函数代码-

未来getAccessToken(String url)异步{

try {
  http.post('url',
      body: {
        "email": "xyz@xyz.com",
        "password": "1234"
      }).then((response) {
    print("Reponse status : ${response.statusCode}");
    print("Response body : ${response.body}");
    var myresponse = jsonDecode(response.body);
    String token = myresponse["token"];
  });
} catch (e) {
  print(e.toString());
}

这是完整的错误正文-

E/flutter ( 6264): [ERROR:flutter/shell/common/shell.cc(184)] Dart Error: Unhandled exception: E/flutter ( 6264): HandshakeException: Handshake error in client (OS Error: E/flutter ( 6264):   CERTIFICATE_VERIFY_FAILED: unable to get local issuer certificate(handshake.cc:363)) E/flutter ( 6264): #0      IOClient.send (package:http/src/io_client.dart:33:23) E/flutter ( 6264): <asynchronous suspension> E/flutter ( 6264): #1      BaseClient._sendUnstreamed (package:http/src/base_client.dart:169:38) E/flutter ( 6264): <asynchronous suspension> E/flutter ( 6264): #2     BaseClient.post (package:http/src/base_client.dart:54:7) E/flutter ( 6264): #3      post.<anonymous closure> (package:http/http.dart:70:16) E/flutter ( 6264): #4      _withClient (package:http/http.dart:166:20) E/flutter ( 6264): <asynchronous suspension> E/flutter ( 6264): #5     post (package:http/http.dart:69:5) E/flutter ( 6264): #6     
_MyLoginFormState.getAccessToken (package:chart/main.dart:74:7) E/flutter ( 6264): <asynchronous suspension> E/flutter ( 6264): #7    
_MyLoginFormState.build.<anonymous closure> (package:chart/main.dart:64:29)

16 个答案:

答案 0 :(得分:22)

为了清楚起见,尤其是为了使新手更加顺畅/飞镖,以下是您需要做的事情,以便在您的项目中全局启用此选项:

  1. 在main.dart文件中,添加或导入以下类:
 class MyHttpOverrides extends HttpOverrides{
  @override
  HttpClient createHttpClient(SecurityContext context){
    return super.createHttpClient(context)
      ..badCertificateCallback = (X509Certificate cert, String host, int port)=> true;
  }
}
  1. 在主函数中,在函数定义后添加以下行:

HttpOverrides.global =新的MyHttpOverrides();

This评论对于解决此问题非常有帮助

答案 1 :(得分:10)

如果您使用的是Dio library,请执行以下操作:

Dio dio = new Dio();
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
    (HttpClient client) {
  client.badCertificateCallback =
      (X509Certificate cert, String host, int port) => true;
  return client;
};

答案 2 :(得分:7)

此代码对我有用

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(MyApp());
}

我想你也会一样...

答案 3 :(得分:6)

我发现正确的方法(但很糟糕)是允许所有证书。

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

String url ='xyz@xyz.com';
Map map = { "email" : "email" , "password" : "password};
HttpClientRequest request = await client.postUrl(Uri.parse(url));
request.headers.set('content-type', 'application/json');
request.add(utf8.encode(json.encode(map)));
HttpClientResponse response = await request.close();
String reply = await response.transform(utf8.decoder).join();
print(reply);

答案 4 :(得分:6)

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

    Future getAccessToken(String url) async {
      try {
        final ioc = new HttpClient();
        ioc.badCertificateCallback =
            (X509Certificate cert, String host, int port) => true;
        final http = new IOClient(ioc);
        http.post('url', body: {"email": "xyz@xyz.com", "password": "1234"}).then(
            (response) {
          print("Reponse status : ${response.statusCode}");
          print("Response body : ${response.body}");
          var myresponse = jsonDecode(response.body);
          String token = myresponse["token"];
        });
      } catch (e) {
        print(e.toString());
      }
    }

答案 5 :(得分:2)

为了解决问题而不是允许一切而登陆这里的每个人。

对我来说,问题在服务器端解决了(应该是这样),代码没有改变。现在一切都有效。在所有其他解决方案中,问题仍然存在(例如,邮递员运行但它在响应状态旁边的地球上显示配置错误) 配置是Centos/Apache/LetsEncrypt/Python3.8/Django3.1.5/Mod_wsgi/ 但我猜这个解决方案对大多数Apache/LetsEncrypt的安装都有效

解决步骤是

  1. 在要配置的虚拟主机上找到“SSLCACertificateFile”行。例如:
<块引用>

SSLCACertificateFile /etc/httpd/conf/ssl.crt/my_ca.crt

  1. 下载 https://letsencrypt.org/certs/lets-encrypt-r3-cross-signed.txt 在 /etc/httpd/conf/ssl.crt/my_ca.crt 的末尾(在 -----END CERTIFICATE----- 之后)开始一个新行并从lets-encrypt-r3-cross-signed 粘贴.txt 所有内容 -----BEGIN CERTIFICATE-----(包括 -----BEGIN CERTIFICATE-----)
  2. 保存/etc/httpd/conf/ssl.crt/my_ca.crt
  3. 重启 Apache httpd

参考资料: https://access.redhat.com/solutions/43575 https://letsencrypt.org/certs

您也可以在 https://www.digicert.com/help/ 中检查证书的有效性。

答案 6 :(得分:2)

这个问题发生在我们身上,因为我们没有使用在 nginx 上使用 let's encrypt 生成的 fullchain.pem。更改后即可解决此问题。

server {
    listen 443 ssl;

    ssl_certificate /var/www/letsencrypt/fullchain.pem;

对于 Apache,您可能需要配置 SSLCertificateChainFile。关于问题的更多讨论 https://github.com/flutter/flutter/issues/50699

答案 7 :(得分:2)

在设备设置中检查设备日期和时间。设备日期和时间设置为上一个日期。

答案 8 :(得分:1)

我特别需要使用lib/client.dart Client接口进行http调用(即http.Client而不是HttpClient)。 ChopperClientlink)要求这样做。

因此,我无法将HttpClient的{​​{1}}直接传递给Chopper。 ChopperClient可以在lib/_http/http.dart中包装的构造函数中接收HttpClient

ioclient.IOClient

这样,您可以暂时忽略通话中的CERTIFICATE_VERIFY_FAILED错误。请记住-仅用于开发目的。不要在生产环境中使用它!

答案 9 :(得分:1)

(我认为)最好的方法是为受信任的主机允许证书,因此,如果您的API主机为"api.my_app",则只能允许来自此主机的证书:

HttpClient client = new HttpClient();
client.badCertificateCallback = ((X509Certificate cert, String host, int port) {
 final isValidHost = host == "api.my_app";
 return isValidHost;
});

如果您有更多主机,则可以在其中添加新的支票。

答案 10 :(得分:1)

对我来说,这是因为我使用的是 HTTPS,而 API 使用的是 HTTP,所以我只是将其更改为 HTTP 并且可以正常工作。

答案 11 :(得分:1)

实际上,就我而言,它在我更新电脑上的日期和时间后修复了我。我猜可能会帮助某人

答案 12 :(得分:0)

使用tls 1.3请求URL,没问题。 例子

import 'dart:io';

main() async {
  HttpClient client = new HttpClient();
  // tls 1.2 error
//  var request = await client.getUrl(Uri.parse('https://shop.io.mi-img.com/app/shop/img?id=shop_88f929c5731967cbc8339cfae1f5f0ec.jpeg')); 
  // tls 1.3 normal
  var request = await client.getUrl(Uri.parse('https://ae01.alicdn.com/kf/Ud7cd28ffdf6e475c8dc382380d5d1976o.jpg'));
  var response = await request.close();
  print(response.headers);
  client.close(force: true);
}

答案 13 :(得分:0)

使用 Dio package 在我的本地服务器上使用自签名证书进行请求,我更喜欢允许特定主机而不是所有域。

//import 'package:get/get.dart' hide Response;  //<-- if you use get package
import 'package:dio/dio.dart';

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

class MyHttpOverrides extends HttpOverrides{
  @override
  HttpClient createHttpClient(SecurityContext context){
    return super.createHttpClient(context)
      ..badCertificateCallback = ((X509Certificate cert, String host, int port) {
        final isValidHost = ["192.168.1.67"].contains(host); // <-- allow only hosts in array
        return isValidHost;
      });
  }
}

// more example: https://github.com/flutterchina/dio/tree/master/example
void getHttp() async {
  Dio dio = new Dio();
  Response response;
  response = await dio.get("https://192.168.1.67");
  print(response.data);
}

答案 14 :(得分:0)

好吧,我发现问题的真正根源是测试设备上的时钟不同步...

答案 15 :(得分:-2)

通常,当您无法使用外部程序包时会发生此问题,而当您的PC中有严格的防火墙设置时,就会发生此问题。大多数情况下,当您使用公司提供的PC时,它们会安装特殊程序来阻止这些服务。因此,请禁用它们,并希望它会起作用。