javax.net.ssl.SSLHandshakeException:java.security.cert.CertPathValidatorException:未找到证书路径的信任锚 [英] javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found

查看:60
本文介绍了javax.net.ssl.SSLHandshakeException:java.security.cert.CertPathValidatorException:未找到证书路径的信任锚的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Retrofit 访问我的 REST API.但是,当我将 API 放在 ssl 之后并通过 http://myhost/myapi 访问它时,我收到此错误:

既然我的 API 位于 SSL 之后,我是否需要做一些额外的事情?

这是我的连接方式:

private final String API = "https://myhost/myapi";私有最终 RestAdapter REST_ADAPTER = 新 RestAdapter.Builder().setServer(API).setLogLevel(RestAdapter.LogLevel.FULL).建造();01-10 09:49:55.621 2076-2100/com.myapp.mobile D/Retrofit:javax.net.ssl.SSLHandshakeException:java.security.cert.CertPathValidatorException:未找到认证路径的信任锚.在 org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:401)在 libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:209)在 libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:478)在 libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:433)在 libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)在 libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)在 libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282)在 libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:497)在 libcore.net.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:134)在改造.client.UrlConnectionClient.readResponse(UrlConnectionClient.java:90)在改造.client.UrlConnectionClient.execute(UrlConnectionClient.java:48)在改造.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:287)在改造.RestAdapter$RestHandler.invoke(RestAdapter.java:222)在 $Proxy12.signin(本地方法)在 com.myapp.loginactivity$3.doInBackground(LoginActivity.java:143)在 com.myapp.loginactivity$3.doInBackground(LoginActivity.java:136)在 android.os.AsyncTask$2.call(AsyncTask.java:287)在 java.util.concurrent.FutureTask.run(FutureTask.java:234)在 android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)在 java.lang.Thread.run(Thread.java:841)引起:java.security.cert.CertificateException:java.security.cert.CertPathValidatorException:未找到证书路径的信任锚.在 org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:282)在 org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:202)在 org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:595)在 org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(本机方法)在 org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:398)在 libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:209)在 libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:478)在 libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:433)在 libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)在 libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)在 libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282)在 libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:497)在 libcore.net.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:134)在改造.client.UrlConnectionClient.readResponse(UrlConnectionClient.java:90)在改造.client.UrlConnectionClient.execute(UrlConnectionClient.java:48)在改造.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:287)在改造.RestAdapter$RestHandler.invoke(RestAdapter.java:222)在 $Proxy12.signin(本地方法)在 com.myapp.LoginActivity$3.doInBackground(LoginActivity.java:143)在 com.myapp.LoginActivity$3.doInBackground(LoginActivity.java:136)在 android.os.AsyncTask$2.call(AsyncTask.java:287)在 java.util.concurrent.FutureTask.run(FutureTask.java:234)在 android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)在 java.lang.Thread.run(Thread.java:841)

解决方案

出现这种情况的原因是 JVM/Dalvik 对系统或用户证书存储中的 CA 证书不信任.

要通过 Retrofit 解决此问题,如果您使用 okhttp,则与另一个客户端非常相似.
你必须这样做:

A).创建一个包含 CA 公钥的证书存储.为此,您需要为 *nix 启动下一个脚本.你需要在你的机器上安装 openssl,然后从 https://www.bouncycastle.org/ 下载 jar bcprov-jdk16-1.46.jar.不下载这个版本另外,1.5x版本不兼容android 4.0.4.

#!/bin/bash如果 [ -z $1 ];然后echo "用法:cert2Android"出口 1菲CACERT=$1BCJAR=bcprov-jdk16-1.46.jarTRUSTSTORE=mytruststore.bksALIAS=`openssl x509 -inform PEM -subject_hash -noout -in $CACERT`如果 [ -f $TRUSTSTORE ];然后rm $TRUSTSTORE ||出口 1菲echo "将证书添加到 $TRUSTSTORE..."keytool -import -v -trustcacerts -alias $ALIAS -file $CACERT -keystore $TRUSTSTORE -storetype BKS -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath $BCJAR -storepass 秘密回声"echo "将别名为 '$ALIAS' 的 '$CACERT' 添加到 $TRUSTSTORE..."

B).将文件 truststore mytruststore.bks 复制到项目的 res/raw 中

C).设置连接的 SSLContext:

<预><代码>........okHttpClient = new OkHttpClient();尝试 {KeyStore ksTrust = KeyStore.getInstance("BKS");InputStream instream = context.getResources().openRawResource(R.raw.mytruststore);ksTrust.load(instream, "secret".toCharArray());//TrustManager 决定使用哪些证书颁发机构.TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());tmf.init(ksTrust);SSLContext sslContext = SSLContext.getInstance("TLS");sslContext.init(null, tmf.getTrustManagers(), null);okHttpClient.setSslSocketFactory(sslContext.getSocketFactory());} catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException | KeyManagementException e) {e.printStackTrace();}………………

I am using Retrofit to access my REST API. However, when I put my API behind ssl and access it by http://myhost/myapi then I get this error:

Do I need to do something extra now that my API is behind SSL?

Here is how I connect:

private final String API = "https://myhost/myapi";

private final RestAdapter REST_ADAPTER = new RestAdapter.Builder()
        .setServer(API)
        .setLogLevel(RestAdapter.LogLevel.FULL)
        .build();

01-10 09:49:55.621    2076-2100/com.myapp.mobile D/Retrofit﹕ javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
            at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:401)
            at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:209)
            at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:478)
            at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:433)
            at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)
            at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)
            at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282)
            at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:497)
            at libcore.net.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:134)
            at retrofit.client.UrlConnectionClient.readResponse(UrlConnectionClient.java:90)
            at retrofit.client.UrlConnectionClient.execute(UrlConnectionClient.java:48)
            at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:287)
            at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:222)
            at $Proxy12.signin(Native Method)
            at com.myapp.loginactivity$3.doInBackground(LoginActivity.java:143)
            at com.myapp.loginactivity$3.doInBackground(LoginActivity.java:136)
            at android.os.AsyncTask$2.call(AsyncTask.java:287)
            at java.util.concurrent.FutureTask.run(FutureTask.java:234)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
            at java.lang.Thread.run(Thread.java:841)
     Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
            at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:282)
            at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:202)
            at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:595)
            at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
            at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:398)
            at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:209)
            at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:478)
            at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:433)
            at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)
            at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)
            at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282)
            at libcore.net.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:497)
            at libcore.net.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:134)
            at retrofit.client.UrlConnectionClient.readResponse(UrlConnectionClient.java:90)
            at retrofit.client.UrlConnectionClient.execute(UrlConnectionClient.java:48)
            at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:287)
            at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:222)
            at $Proxy12.signin(Native Method)
            at com.myapp.LoginActivity$3.doInBackground(LoginActivity.java:143)
            at com.myapp.LoginActivity$3.doInBackground(LoginActivity.java:136)
            at android.os.AsyncTask$2.call(AsyncTask.java:287)
            at java.util.concurrent.FutureTask.run(FutureTask.java:234)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
            at java.lang.Thread.run(Thread.java:841)

解决方案

The reason this occur is the JVM/Dalvik haven't not confidence in the CA certificates in the system or in the user certificate stores.

To fix this with Retrofit, If you are used okhttp, with another client it's very similar.
You've to do:

A). Create a cert store contain public Key of CA. To do this you need to launch next script for *nix. You need openssl install in your machine, and download from https://www.bouncycastle.org/ the jar bcprov-jdk16-1.46.jar. Download this version not other, the version 1.5x is not compatible with android 4.0.4.

#!/bin/bash

if [ -z $1 ]; then
  echo "Usage: cert2Android<CA cert PEM file>"
  exit 1
fi

CACERT=$1
BCJAR=bcprov-jdk16-1.46.jar

TRUSTSTORE=mytruststore.bks
ALIAS=`openssl x509 -inform PEM -subject_hash -noout -in $CACERT`

if [ -f $TRUSTSTORE ]; then
    rm $TRUSTSTORE || exit 1
fi

echo "Adding certificate to $TRUSTSTORE..."
keytool -import -v -trustcacerts -alias $ALIAS 
      -file $CACERT 
      -keystore $TRUSTSTORE -storetype BKS 
      -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider 
      -providerpath $BCJAR 
      -storepass secret

echo "" 
echo "Added '$CACERT' with alias '$ALIAS' to $TRUSTSTORE..."

B). Copy the file truststore mytruststore.bks in res/raw of your project

C). Setting SSLContext of the connection:

.............
okHttpClient = new OkHttpClient();
try {
    KeyStore ksTrust = KeyStore.getInstance("BKS");
    InputStream instream = context.getResources().openRawResource(R.raw.mytruststore);
    ksTrust.load(instream, "secret".toCharArray());

    // TrustManager decides which certificate authorities to use.
    TrustManagerFactory tmf = TrustManagerFactory
        .getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(ksTrust);
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, tmf.getTrustManagers(), null);

    okHttpClient.setSslSocketFactory(sslContext.getSocketFactory());
} catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException | KeyManagementException e) {
    e.printStackTrace();
}
.................

这篇关于javax.net.ssl.SSLHandshakeException:java.security.cert.CertPathValidatorException:未找到证书路径的信任锚的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆