我正在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))
Run Code Online (Sandbox Code Playgroud)
这是我的函数代码-
Future getAccessToken(String url) async {
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());
}
Run Code Online (Sandbox Code Playgroud)
这是完整的错误正文-
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)
Run Code Online (Sandbox Code Playgroud)
Smi*_*ith 97
将这个文件添加到assets/ca/ Flutter项目根目录下
在pubspec.yaml中添加assets/ca/assets目录
在您的应用程序初始化中添加以下代码:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
ByteData data = await PlatformAssetBundle().load('assets/ca/lets-encrypt-r3.pem');
SecurityContext.defaultContext.setTrustedCertificatesBytes(data.buffer.asUint8List());
runApp(MyApp());
}
Run Code Online (Sandbox Code Playgroud)
它与默认链一起使用,因此不需要在服务器上进行任何更改。Android < 7.1.1 客户端仍可以在浏览器上下文中进行访问。
Ma'*_*ash 80
只是为了清楚起见,特别是为了新来者 flutter/dart,为了在项目中全局启用此选项,您需要执行以下操作:
Run Code Online (Sandbox Code Playgroud)class MyHttpOverrides extends HttpOverrides{ @override HttpClient createHttpClient(SecurityContext context){ return super.createHttpClient(context) ..badCertificateCallback = (X509Certificate cert, String host, int port)=> true; } }
HttpOverrides.global = new MyHttpOverrides();
这个评论对通过这个事情很有帮助,请注意......
这应该在开发模式下使用,当你想要发布到生产时不要这样做,这个答案的目的是 让你的开发更容易一些,对于生产,你需要修复你的证书问题并使用它正确地,请查看其他答案,因为它可能对您的情况有所帮助。
Hos*_*our 19
如果您使用的是Dio 库,请执行以下操作:
Dio dio = new Dio();
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
(HttpClient client) {
client.badCertificateCallback =
(X509Certificate cert, String host, int port) => true;
return client;
};
Run Code Online (Sandbox Code Playgroud)
Adi*_*ood 13
我发现,正确的方法(但很糟糕)是允许所有证书。
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);
Run Code Online (Sandbox Code Playgroud)
最好的方法(我认为)是允许可信主机的证书,所以如果你的 API 主机是"api.my_app"
你只能允许来自这个主机的证书:
HttpClient client = new HttpClient();
client.badCertificateCallback = ((X509Certificate cert, String host, int port) {
final isValidHost = host == "api.my_app";
return isValidHost;
});
Run Code Online (Sandbox Code Playgroud)
如果你有更多的主机,你可以在那里添加一个新的检查。
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());
}
}
Run Code Online (Sandbox Code Playgroud)
此代码对我有用
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());
}
Run Code Online (Sandbox Code Playgroud)
我想这对你来说也是一样的......
小智 8
这是针对http库的方法。为了在项目中全局启用此选项,您需要执行以下操作。
class MyHttpoverrides extends HttpOverrides{
@override
HttpClient createHttpClient(SecurityContext context){
return super.createHttpClient(context)
..badCertificateCallback = (X509Certificate cert, String host, int port)=>true;
}
}
//void main() => runApp(MyApp());
void main(){
HttpOverrides.global=new MyHttpoverrides();
runApp(MyApp());
}
Run Code Online (Sandbox Code Playgroud)
使用Dio 包在我的本地服务器上使用自签名证书请求,我更喜欢允许特定主机而不是所有域。
//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);
}
Run Code Online (Sandbox Code Playgroud)
对于每个登陆这里并需要解决问题而不是仅仅绕过它允许一切的人来说。
对我来说,问题在服务器端解决了(应该如此),代码没有任何变化。现在一切都有效了。在所有其他解决方案上,问题仍然存在(例如,邮递员运行,但它在响应状态旁边的地球上显示配置错误)配置是 Centos/Apache/LetsEncrypt/Python3.8/Django3.1.5/Mod_wsgi/ 但我猜该解决方案对于大多数 Apache/LetsEncrypt 安装都有效
解决步骤是
SSLCACertificateFile /etc/httpd/conf/ssl.crt/my_ca.crt
参考资料: https://access.redhat.com/solutions/43575 https://letsencrypt.org/certs
您还可以在https://www.digicert.com/help/中检查证书的有效性。
这个问题发生在我们身上,因为我们没有使用在 nginx 上使用 let's encrypt 生成的 fullchain.pem。一旦更改它就解决了这个问题。
server {
listen 443 ssl;
ssl_certificate /var/www/letsencrypt/fullchain.pem;
Run Code Online (Sandbox Code Playgroud)
对于 Apache,您可能需要配置SSLCertificateChainFile
. 关于该问题的更多讨论https://github.com/flutter/flutter/issues/50699
对于那些只需要忽略某些调用的证书错误的人,您可以使用HttpOverrides
众多答案中已经提到的解决方案。
然而,没有必要在全球范围内使用它。通过将调用包装在HttpOverrides.runWithHttpOverrides()
.
class IgnoreCertificateErrorOverrides extends HttpOverrides{
@override
HttpClient createHttpClient(SecurityContext context){
return super.createHttpClient(context)
..badCertificateCallback = ((X509Certificate cert, String host, int port) {
return true;
});
}
}
Future<void> myNonSecurityCriticalApiCall() async {
await HttpOverrides.runWithHttpOverrides(() async {
String url = 'https://api.example.com/non/security/critical/service';
Response response = await get(Uri.parse(url));
// ... do something with the response ...
}, IgnoreCertificateErrorOverrides());
}
Run Code Online (Sandbox Code Playgroud)
就我而言,它是一个外部 API,它具有有效的 SSL 证书并且可以在浏览器中运行,但由于某种原因无法在我的 Flutter 应用程序中运行。
小智 5
如果您使用 Dio 库,则“DefaultHttpClientAdapter”已被弃用,不应使用。请改用 IOHttpClientAdapter。
首先手动导入:
import 'package:dio/io.dart';
Run Code Online (Sandbox Code Playgroud)
然后使用“IOHttpClientAdapter”而不是“DefaultHttpClientAdapter”
(_dio.httpClientAdapter as IOHttpClientAdapter).onHttpClientCreate =
(HttpClient client) {
client.badCertificateCallback =
(X509Certificate cert, String host, int port) => true;
return client;
};
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
7347 次 |
最近记录: |