8

I am using flutter to connect with java java server implementation over https. I first tested it to be working using just http.

I then switched to https on the server side and pointed it at my self signed certificate I created using keytool.

Then I tried to connect to it using the http dart package. The resulted in the following exception...

Unhandled Exception: HandshakeException: Handshake error in client (OS Error: E/flutter ( 7370): CERTIFICATE_VERIFY_FAILED: self signed certificate(handshake.cc:354))

I am assuming I need to set my client to trust my servers self signed certificate. I have looked at the APi reference and could not figure out how to get this to happen...

My dart code in my flutter app is as follows...

void testMessage() {
    var url = 'https://192.168.100.105:8443';
    var response = await http.post(url, body: "{\"message_name\": \"TestMessage\", \"contents\": { \"field1\":\"blah\", \"field2\":\"blah\" }}");
    print('Response status: ${response.statusCode}');
    print('Response body: ${response.body}');
}
Scorb
  • 1,654
  • 13
  • 70
  • 144

4 Answers4

8

While Pascal's answer works, it only applies to the dart:io HttpClient. To apply the badCertificateCallback to the http package's Client instances, do the following:

Create a class that overrides HttpOverrides in the following way:

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

Then in your main, instantiate your class as the global HttpOverride:

HttpOverrides.global = new DevHttpOverrides();

This should make all Client ignore bad certificates and is therefore onl;y recommended in development. Credit goes to this issue: https://github.com/dart-lang/http/issues/458

Wecherowski
  • 818
  • 11
  • 24
5

While developing you can use the badCertificateCallback callback of HttpClient and just return true. This will accept all bad certificates.

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

To accept a specific bad certificate you may experiment with this code from here: https://github.com/dart-lang/http/issues/14#issuecomment-311184690

import 'dart:io';
import 'package:http/http.dart' as http;

bool _certificateCheck(X509Certificate cert, String host, int port) =>
    host == 'local.domain.ext'; // <- change

HttpClient client = new HttpClient()
    ..badCertificateCallback = (_certificateCheck);
Pascal Werkl
  • 2,918
  • 1
  • 13
  • 14
  • 9
    And how would this snippet be implemented in his code? I am having a similar problem and I'd like to keep using the http package, not the dart/io, since i find the implementation to be easier to read, simpler and shorter – Mike Jul 15 '20 at 12:42
0

Amazing @Wecherowski, I think more safe way to do this is to check the other details and return true.

Something like:

HttpClient createHttpClient(SecurityContext? context)
 {
    return super.createHttpClient(context)
       ..badCertificateCallback = (X509Certificate cert, String host, int port)
       {
         if (host.isNotEmpty && host == 'xyz.example.com')
           {  
               return true;  
           }  
           else  
           {  return false;  }  
 };
Ajeet Singh
  • 417
  • 7
  • 23
-4

If you use dio library https://pub.dev/packages/dio you can make requests from http to https

user3808307
  • 2,270
  • 9
  • 45
  • 99
  • 1
    Please don't just post some tool or library as an answer. At least demonstrate [how it solves the problem](https://meta.stackoverflow.com/a/251605) in the answer itself. – Yunnosch Nov 03 '20 at 18:09
  • There is no special way of using it that solves the problem, @Yunnosch, just using this library makes you not have the problem. This would have been helpful for me to see before deciding which library to use, so I put it as an answer in case it helps others – user3808307 Nov 03 '20 at 20:57