web-dev-qa-db-ja.com

javax.net.ssl.SSLHandshakeException:Java.security.cert.CertPathValidatorException:証明書パスのトラストアンカーが見つかりません

Retrofitを使用して、REST APIにアクセスします。ただし、SSLの背後にAPIを配置し、http://myhost/myapiその後、私はこのエラーを取得します:

APIがSSLの背後にあるため、何か特別なことをする必要がありますか?

接続方法は次のとおりです。

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)
24
birdy

これが発生する理由は、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

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)。プロジェクトのres/rawにあるファイルtruststore mytruststore.bksをコピーします truststore location

C)。接続のSSLContextの設定:

.............
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();
}
.................
12
Fernando.

こんにちは同じ問題を解決しましたこれを試すことができます

Java.security.cert.CertPathValidatorException:証明書パスのトラストアンカーが見つかりません。NETWORK

 // SET SSL
public static OkClient setSSLFactoryForClient(OkHttpClient client) {
    try {
        // Create a trust manager that does not validate certificate chains
        final TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    @Override
                    public void checkClientTrusted(Java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                    }

                    @Override
                    public void checkServerTrusted(Java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                    }

                    @Override
                    public Java.security.cert.X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }
                }
        };

        // Install the all-trusting trust manager
        final SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null, trustAllCerts, new Java.security.SecureRandom());
        // Create an ssl socket factory with our all-trusting manager
        final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();


        client.setSslSocketFactory(sslSocketFactory);
        client.setHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });

    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    return new OkClient(client);
}
2
sushant gosavi

これは、次のようないくつかの理由で発生する可能性があります。

  1. サーバー証明書を発行したCAは不明でした
  2. サーバー証明書はCAによって署名されていませんが、自己署名されています
  3. サーバー構成に中間CAがありません

解決策については、このリンクを確認してください: https://developer.Android.com/training/articles/security-ssl.html#CommonProblems

2
Defuera

私が知っている4つの方法があります:

  • アプリに証明書をインポートし、接続に使用します
  • 証明書チェックを無効にする
  • 証明書をAndroidの信頼できるシステム証明書に追加します
  • androidで受け入れられる検証済みの証明書を購入する

あなたはこれにお金を払いたくないと思うので、最もエレガントな解決策は最初の解決策であり、この方法で達成できることだと思います:

http://blog.crazybob.org/2010/02/Android-trusting-ssl-certificates.html

2
kupsef

SSLが正しく構成されていません。通常、これらのtrustAnchorエラーは、トラストストアが見つからないことを意味します。構成を確認し、実際にトラストストアを指していること、およびそれが適切であることを確認してください。

-Djavax.net.ssl.trustStoreシステムプロパティが設定されていることを確認してから、パスが実際にトラストストアにつながることを確認してください。

このシステムプロパティ-Djavax.net.debug=allを設定して、SSLデバッグを有効にすることもできます。デバッグ出力内で、トラストストアが見つからないことが示されていることがわかります。

1
Kevin Bowersox

私はこのクラスを使用していますが、問題はありません。

public class WCFs
{
    //  https://192.168.30.8/myservice.svc?wsdl
private static final String NAMESPACE = "http://tempuri.org/";
private static final String URL = "192.168.30.8";
private static final String SERVICE = "/myservice.svc?wsdl";
private static String SOAP_ACTION = "http://tempuri.org/iWCFserviceMe/";


public static Thread myMethod(Runnable rp)
{
    String METHOD_NAME = "myMethod";

    SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);

    request.addProperty("Message", "Https WCF Running...");
    return _call(rp,METHOD_NAME, request);
}

protected static HandlerThread _call(final RunProcess rp,final String METHOD_NAME, SoapObject soapReq)
{
    final SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
    int TimeOut = 5*1000;

    envelope.dotNet = true;
    envelope.bodyOut = soapReq;
    envelope.setOutputSoapObject(soapReq);

    final HttpsTransportSE httpTransport_net = new HttpsTransportSE(URL, 443, SERVICE, TimeOut);

    try
    {
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() // use this section if crt file is handmake
        {
            @Override
            public boolean verify(String hostname, SSLSession session)
            {
                return true;
            }
        });

        KeyStore k = getFromRaw(R.raw.key, "PKCS12", "password");
        ((HttpsServiceConnectionSE) httpTransport_net.getServiceConnection()).setSSLSocketFactory(getSSLSocketFactory(k, "SSL"));


    }
    catch(Exception e){}

    HandlerThread thread = new HandlerThread("wcfTd"+ Generator.getRandomNumber())
    {
        @Override
        public void run()
        {
            Handler h = new Handler(Looper.getMainLooper());
            Object response = null;

            for(int i=0; i<4; i++)
            {
                response = send(envelope, httpTransport_net , METHOD_NAME, null);

                try
                {if(Thread.currentThread().isInterrupted()) return;}catch(Exception e){}

                if(response != null)
                    break;

                ThreadHelper.threadSleep(250);
            }

            if(response != null)
            {
                if(rp != null)
                {
                    rp.setArguments(response.toString());
                    h.post(rp);
                }
            }
            else
            {
                if(Thread.currentThread().isInterrupted())
                    return;

                if(rp != null)
                {
                    rp.setExceptionState(true);
                    h.post(rp);
                }
            }

            ThreadHelper.stopThread(this);
        }
    };

    thread.start();

    return thread;
}


private static Object send(SoapSerializationEnvelope envelope, HttpTransportSE androidHttpTransport, String METHOD_NAME, List<HeaderProperty> headerList)
{
    try
    {
        if(headerList != null)
            androidHttpTransport.call(SOAP_ACTION + METHOD_NAME, envelope, headerList);
        else
            androidHttpTransport.call(SOAP_ACTION + METHOD_NAME, envelope);

        Object res = envelope.getResponse();

        if(res instanceof SoapPrimitive)
            return (SoapPrimitive) envelope.getResponse();
        else if(res instanceof SoapObject)
            return ((SoapObject) envelope.getResponse());
    }
    catch(Exception e)
    {}

    return null;
}

public static KeyStore getFromRaw(@RawRes int id, String algorithm, String filePassword)
{
    try
    {
        InputStream inputStream = ResourceMaster.openRaw(id);
        KeyStore keystore = KeyStore.getInstance(algorithm);
        keystore.load(inputStream, filePassword.toCharArray());
        inputStream.close();

        return keystore;
    }
    catch(Exception e)
    {}

    return null;
}

public static SSLSocketFactory getSSLSocketFactory(KeyStore trustKey, String SSLAlgorithm)
{
    try
    {
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustKey);

        SSLContext context = SSLContext.getInstance(SSLAlgorithm);//"SSL" "TLS"
        context.init(null, tmf.getTrustManagers(), null);

        return context.getSocketFactory();
    }
    catch(Exception e){}

    return null;
}

}

0
Ali Bagheri