Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android java.security.cert.CertificateException:java.security.cert.CertPathValidatorException:找不到证书路径的信任锚点_Android_Ssl_Android Volley_X509certificate - Fatal编程技术网

Android java.security.cert.CertificateException:java.security.cert.CertPathValidatorException:找不到证书路径的信任锚点

Android java.security.cert.CertificateException:java.security.cert.CertPathValidatorException:找不到证书路径的信任锚点,android,ssl,android-volley,x509certificate,Android,Ssl,Android Volley,X509certificate,使用X509TrustManager检查服务器是否受信任时,我收到一个异常错误。我遵循开发者的指示: 我正在尝试获取存储在我的应用程序中的本地证书,并将该证书与我发出的每个Volley API请求一起使用,以首先确认该证书是否可信(已验证)。我从GoDaddy下载了证书并将其添加到我的项目:。我得到的确切错误如下: 06-09 15:01:20.509 10599-11180/com.app.debug W/System.err: java.security.cert.CertificateEx

使用X509TrustManager检查服务器是否受信任时,我收到一个异常错误。我遵循开发者的指示:

我正在尝试获取存储在我的应用程序中的本地证书,并将该证书与我发出的每个Volley API请求一起使用,以首先确认该证书是否可信(已验证)。我从GoDaddy下载了证书并将其添加到我的项目:。我得到的确切错误如下:

06-09 15:01:20.509 10599-11180/com.app.debug W/System.err: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:     at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:324)
06-09 15:01:20.519 10599-11070/com.app.debug I/System.out: (HTTPLog)-Static: isSBSettingEnabled false
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:     at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:215)
06-09 15:01:20.519 10599-11070/com.app.debug I/System.out: (HTTPLog)-Static: isSBSettingEnabled false
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:     at com.udi.app.framework.net.VolleyClient$3.checkServerTrusted(SourceFile:170)
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:     at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:117)
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:     at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:643)
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:     at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:     at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:353)
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:     at com.android.okhttp.internal.http.SocketConnector.connectTls(SocketConnector.java:212)
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:     at com.android.okhttp.Connection.connect(Connection.java:1322)
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:     at com.android.okhttp.Connection.connectAndSetOwner(Connection.java:1410)
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:     at com.android.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:128)
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:     at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:466)
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:     at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:447)
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:     at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:353)
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:     at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:468)
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:     at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:410)
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:     at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:532)
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:     at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getResponseCode(DelegatingHttpsURLConnection.java:105)
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:     at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:25)
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:     at com.android.volley.toolbox.HurlStack.performRequest(SourceFile:109)
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:     at com.android.volley.toolbox.BasicNetwork.performRequest(SourceFile:93)
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:     at com.android.volley.NetworkDispatcher.run(SourceFile:105)
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err: Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
06-09 15:01:20.519 10599-11180/com.app.debug W/System.err:  ... 22 more
我有一个名为“VolleyClient”的类,它管理我通过Volley发出的所有请求。这是我的实现。我首先用截击请求队列传入一个HurlStack对象

HurlStack hurlStack = new HurlStack() {
                @Override
                protected HttpURLConnection createConnection(URL url) throws IOException {
                    HttpsURLConnection httpsURLConnection = (HttpsURLConnection) super.createConnection(url);
                    try {
                        httpsURLConnection.setSSLSocketFactory(getSSLSocketFactory());
                        httpsURLConnection.setHostnameVerifier(getHostnameVerifier());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return httpsURLConnection;
                }
            };

RequestQueue mRequestQueue = Volley.newRequestQueue(mContext.getApplicationContext(), hurlStack);
我有一个主机名验证器

/**
 * This is used to verify local host. Let's assume the app is hosted inside of a server
 * machine which has a server certificate in which "Issued to" is "localhost", then
 * this method will verify "localhost". If not, can temporarily return true
 * @return
 */
private HostnameVerifier getHostnameVerifier() {
    return new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            //return true;
            HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
            return hv.verify("localhost", session);
        }
    };
}

private SSLSocketFactory getSSLSocketFactory()
        throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, KeyManagementException {

    InputStream caInput = mContext.getResources().openRawResource(R.raw.gdig2); // this certificate file stored in \app\src\main\res\raw folder path
    // From https://www.washington.edu/itconnect/security/ca/load-der.crt
    //InputStream caInput = new BufferedInputStream(new FileInputStream("load-der.crt"));
    CertificateFactory cf = null;
    Certificate ca = null;
    try {
        cf = CertificateFactory.getInstance("X.509", "BC");
        ca = cf.generateCertificate(caInput);
        System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
    } catch (NoSuchProviderException e) {
        e.printStackTrace();
    } finally {
        caInput.close();
    }
    caInput.close();

    // Create a KeyStore containing our trusted CAs
    String keyStoreType = KeyStore.getDefaultType();
    KeyStore keyStore = KeyStore.getInstance(keyStoreType); //KeyStore keyStore = KeyStore.getInstance("BKS");
    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);

    TrustManager[] wrappedTrustManagers = getWrappedTrustManagers(tmf.getTrustManagers());

    // Create an SSLContext that uses our TrustManager
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, wrappedTrustManagers, null);

    return sslContext.getSocketFactory();
}

private TrustManager[] getWrappedTrustManagers(TrustManager[] trustManagers) {
    final X509TrustManager originalTrustManager = (X509TrustManager) trustManagers[0];
    return new TrustManager[]{
            new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return originalTrustManager.getAcceptedIssuers();
                }

                public void checkClientTrusted(X509Certificate[] certs, String authType) {
                    try {
                        originalTrustManager.checkClientTrusted(certs, authType);
                    } catch (CertificateException e) {
                        e.printStackTrace();
                    }
                }

                public void checkServerTrusted(X509Certificate[] certs, String authType) {
                    try {
                        originalTrustManager.checkServerTrusted(certs, authType);
                    } catch (CertificateException e) {
                        // THIS IS THE EXCEPTION I GET WITH EACH REQUEST MADE
                        e.printStackTrace();
                    }
                }
            }
    };
}
提前谢谢

编辑:当调用谷歌时会发生此异常,因为我使用的是谷歌地图。此调用不使用来自我的服务器的已验证证书,因此导致证书路径未找到异常的信任锚点

我可以通过总是返回true来规避这个问题,但这是正确的吗?我应该返回服务器的域吗

private HostnameVerifier getHostnameVerifier() {
    return new HostnameVerifier() {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            // instead should I return back hv.verify("https:myserver.com", session);
            return true; 
        }
    };
}

检查系统时间。请确保它是最新的。

请使用我的最新答案。此外,如果您在Android中使用的证书与web服务中的证书相同,那么您可以使用“tmf.getrustmanagers”而不是getWrapp…@BNK您的答案与我实现的答案非常相似,但是,我仍然不确定返回什么作为主机名。您评论说“verify总是返回true,这可能会由于信任TLS/SSL服务器证书以获得错误的主机名而导致不安全的网络通信”。这是否意味着我应该指定我的服务器主机名?我认为HostnameVerifier不会导致异常“信任锚…”。它用于“java.io.IOException:Hostname'example.com'未经验证”,如在Google Doc中。请告诉我,如果您使用verify(…)而不是“return true”,logcat中有任何错误吗?如何准确更改时间以使不受信任的证书可信?请解释一下。