Android SSL - CertPathValidatorException

时间:2017-03-03 11:39:21

标签: android ssl tomcat7

我的HTTPS服务托管在TomCat中(在JDK bin中借助keytool创建的.keystore)。

服务器证书是自签名的&通过在受信任的根权限中安装它使其成为受信任的。

我可以从浏览器访问该服务。但无法从Android中做同样的事情。

有人请帮忙。我是J2EE的新手

enter image description here

使用OpenSSL创建

host.cert (置于资产目录中)。

我正在使用Android开发者网站的代码段

        try {
            // Load CAs from an InputStream
// (could be from a resource or ByteArrayInputStream or ...)
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
// From https://www.washington.edu/itconnect/security/ca/load-der.crt

            InputStream inn=getAssets().open("host.cert");

            Certificate ca;
            try {
                ca = cf.generateCertificate(inn);
                Log.i("TEST","ca=" + ((X509Certificate) ca).getSubjectDN());
            } finally {
                inn.close();
            }

// 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);

// Tell the URLConnection to use a SocketFactory from our SSLContext
            URL url = new URL("https://192.168.56.1:8443/RestHTTPS/JavaCodeGeeks/AuthorService/authors/");
            HttpsURLConnection urlConnection =
                    (HttpsURLConnection)url.openConnection();
            urlConnection.setSSLSocketFactory(context.getSocketFactory());
            InputStream in = urlConnection.getInputStream();

            byte arr[]=new byte[in.available()];
            in.read(arr);

            String str=new String(arr);
            Log.i("TEST",str);

        }catch (Exception e){
            Log.e("TEST",e.toString());
            e.printStackTrace();
        }

我知道,这已经被问到了问题。但我找不到解决方案。

1 个答案:

答案 0 :(得分:0)

我会发布解决方案,对于仍然面临问题的人。

主要注意3件事(已在Android developer site中说明)

  • 创建自定义信任管理器以绕过默认信任管理器。
  • 手动验证主机名是否可接受。
  • 永远不要使用" localhost"或" 127.0.0.1"出于测试目的,请使用您的PC的IP地址。

这是完整的代码

try {

            // Things to Note 1 : Bypass default Trust Managers
            TrustManager[] byPassTrustManagers = new TrustManager[]{new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }

                public void checkClientTrusted(X509Certificate[] chain, String authType) {
                }

                public void checkServerTrusted(X509Certificate[] chain, String authType) {
                }
            }};

            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            InputStream inn = getAssets().open("keystore.cer");
            Certificate ca;
            try {
                ca = cf.generateCertificate(inn);
                Log.i("TEST", "ca=" + ((X509Certificate) ca).getSubjectDN());
            } finally {
                inn.close();
            }


            String keyStoreType = "BKS";
            KeyStore.getDefaultType();
            KeyStore keyStore = KeyStore.getInstance(keyStoreType);
            keyStore.load(null, null);
            keyStore.setCertificateEntry("ca", ca);

            String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
            tmf.init(keyStore);

            SSLContext context = SSLContext.getInstance("TLS");
            context.init(null, byPassTrustManagers, null);

            // Things to Note 2 : Don't use "localhost" ,instead use IP
            URL url = new URL("https://192.168.56.1:8443/RestHTTPS/JavaCodeGeeks/AuthorService/authors");
            HttpsURLConnection urlConnection =
                    (HttpsURLConnection) url.openConnection();

            urlConnection.setSSLSocketFactory(context.getSocketFactory());

            // Things to Note 3 : Allow all host
            urlConnection.setHostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });

            Log.i("TEST", urlConnection.getResponseMessage() + "");

            InputStream in = urlConnection.getInputStream();

            InputStreamReader isw = new InputStreamReader(in);

            int data = isw.read();
            String str = "";
            while (data != -1) {
                char current = (char) data;
                data = isw.read();
                str += current;
            }

            Log.i("TEST", "" + str);

        } catch (Exception e) {
            Log.e("TEST", e.toString());
            e.printStackTrace();
        }