Android 尝试信任自签名证书,出现无对等连接错误

Android Trying to trust a self signed certificate, get a no peer connection error

我有以下代码:

  AsyncTask asyncTask = new AsyncTask() {
        @Override
        protected Object doInBackground(Object[] params) {
            try {
                HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;

                DefaultHttpClient client = new DefaultHttpClient();

                SchemeRegistry registry = new SchemeRegistry();
                SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
                socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
                registry.register(new Scheme("https", socketFactory, 443));
                SingleClientConnManager mgr = new SingleClientConnManager(client.getParams(), registry);
                DefaultHttpClient httpClient = new DefaultHttpClient(mgr, client.getParams());

// Set verifier
                HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);

// Example send http request
                final String url = "https://192.168.1.13:8090/version";
                HttpPost httpPost = new HttpPost(url);
                HttpResponse response = httpClient.execute(httpPost);
                Log.i("","response is:" + response);
            }catch (Exception e){
                Log.e("","error trying to get:" + e.getMessage());
            }
            return null;
        }
    };
    asyncTask.execute();

我遇到以下问题:

10-12 10:53:37.546: E/(24916): error trying to get:No peer certificate
10-12 10:53:38.890: E/Finsky(18904): [1] com.google.android.vending.verifier.ah.a(713): Verification id=44 error response com.android.volley.NoConnectionError: java.net.UnknownHostException: Unable to resolve host "safebrowsing.google.com": No address associated with hostname

我做错了什么?

我确实使用这种方法获得了正确的响应:

 AsyncTask asyncTask = new AsyncTask() {
        @Override
        protected Object doInBackground(Object[] params) {
            HttpsURLConnection conn = null;
            try {
                URL url = new URL("https://192.168.1.13:8090/version");
                conn = (HttpsURLConnection) url.openConnection();
                conn.setSSLSocketFactory(SSLCertificateSocketFactory.getInsecure(0, null));
                conn.setHostnameVerifier(new AllowAllHostnameVerifier());
                conn.setRequestProperty("Accept-Charset", "UTF-8");
                conn.connect();
                InputStream response = conn.getInputStream();
                BufferedReader br = new BufferedReader(new InputStreamReader(response, "utf8"));
                StringBuffer sb = new StringBuffer();
                String line = "";

                while ((line = br.readLine()) != null) {
                    sb.append(line);
                }

                String data = sb.toString();
                Log.i("","response is:" + data);
            } catch (MalformedURLException e) {
                Log.e("","error trying to get conn:" + e.getMessage());
            } catch (IOException e) {
                Log.e("","error trying to get conn2:" + e.getMessage());
            }
            return null;
        }
    };
    asyncTask.execute();

我获得了一个使用 ip 而不是域的自我叹息证书。如果您想使用域,只需跳过 "connection.setHostnameVerifier" 部分。

我使用 192.168.1.100 作为 "Common Name" 生成证书如下,即 CN=

openssl req -new -newkey rsa:2048 -nodes -out mydomain.csr -keyout private.key

openssl req -key private.key -new -x509 -days 9999 -out primary.crt

@Override
    protected String doInBackground(String... params)
    {      
        if(params.length >=2)
        {
            try {
                Log.w("doInBackground[0]", params[0]);
                Log.w("doInBackground[1]", params[1]);
                Log.w("doInBackground[2]", params[2]);
            }catch (Exception exlog){}

            //HttpURLConnection connection = null;
            HttpsURLConnection connection = null;
            String reply = "{ alert : { 'type' : 'error' , 'message':'GetJSON failed'}}";

            try
            {
                // My CRT file that I put in the assets folder
                CertificateFactory cf = CertificateFactory.getInstance("X.509");
                InputStream caInput = new BufferedInputStream(context.getAssets().open("primary.crt"));//crt private.key
                Certificate ca = cf.generateCertificate(caInput);
                System.out.println("CA=" + ((X509Certificate) ca).getSubjectDN());

                // Create a KeyStore containing our trusted CAs
                String keyStoreType = KeyStore.getDefaultType();
                KeyStore keyStore = KeyStore.getInstance(keyStoreType);
                keyStore.load(null, null);
                keyStore.setCertificateEntry("ca", ca);

                // Create a TrustManager that trusts the CAs in our KeyStore
                String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
                TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
                tmf.init(keyStore);

                // Create an SSLContext that uses our TrustManager
                SSLContext context = SSLContext.getInstance("TLS");
                context.init(null, tmf.getTrustManagers(), null);


                //Set Network IO
                URL url = new URL(params[0].toString());
                //connection = (HttpURLConnection) url.openConnection();
                connection = (HttpsURLConnection) url.openConnection();
                connection.setSSLSocketFactory(context.getSocketFactory());
                connection.setHostnameVerifier(new HostnameVerifier()                {
                    @Override
                    public boolean verify(String hostname, SSLSession session)
                    {
                        if(hostname.equals("192.168.1.100")) {
                            return true;
                        } else {
                            return false;
                        }
                    }
                });

                // Use this if you need SSL authentication
                //String userpass = user + ":" + password;
                //String basicAuth = "Basic " + Base64.encodeToString(userpass.getBytes(), Base64.DEFAULT);
                // connection.setRequestProperty("Authorization", basicAuth);

                //Build Header
                connection.setDoInput(true);            
                connection.setUseCaches(false);
                connection.setReadTimeout(45000);
                connection.setConnectTimeout(45000);
                connection.setRequestMethod("GET");
                connection.setRequestProperty("Content-Type", "application/json");
                connection.setRequestProperty("charset", "utf-8");

                if(params.length == 3 && params[2]!= null && !params[2].equals(""))                {
                    connection.setRequestProperty("Authorization" , params[2]);
                }                         

                //Get Reply Status 400, 404, 200
                String http_code = String.valueOf(connection.getResponseCode());
                String http_message = connection.getResponseMessage();
                Log.w(http_code, http_message);

                //Read Response
                InputStream in = connection.getInputStream();
                reply = this.convertStreamToString(in);
                Log.w(LOG_HEADER + ":REPLY", reply);
            }
            catch (IOException ioe)            {
                Log.d(LOG_HEADER +"IO:ERR", ioe.getMessage());
            }
            catch (Exception ex)            {
                Log.d(LOG_HEADER + ":ERR", ex.getMessage());
            } finally {
                if (connection != null) {
                    connection.disconnect();
                }
                Log.w(LOG_HEADER + ":END", "Connection Closed");
            }

            return reply;
        }
        else
        {            
            return "{ alert : { 'type' : 'error' , 'message':" + LOG_HEADER + "'}}";
        }
    }