7

私のアンドロイド プロジェクトは api 15 を使用しています。HttpsURLConnection クラスを使用して、https 経由でサーバーに接続しています。WiFi 経由ではすべて正常に動作しますが、WiFi をオフにして 3g 経由で実行すると、次のようになります。

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:413)
   at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:257)       at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:210)
   at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:477)
   at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:432)
   at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:282)
   at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:232)       at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:80)
   at libcore.net.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:188)       at libcore.net.http.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:280)

私が何か間違ったことをしている場合、なぜ WiFi 経由で動作するのでしょうか?

ここでもう少し情報を。

openssl を使用してサーバー証明書情報を表示すると、

echo | openssl s_client -connect myserver.com:443

サーバーレベルの自己署名証明書を返しますが、

echo | openssl s_client -connect myserver.com:443 -servername myserver.com

「正しい」証明書を返します。サーバーには複数の仮想ホストがあり、それぞれが独自のrapidssl発行の証明書を持っているため、TLS対応のクライアントを使用する必要があると「考えています」。少なくとも、起動時の Apache ログに表示されるメッセージの私の解釈は次のとおりです。

Name-based SSL virtual hosts only work for clients with TLS server name indication support

これまでのところ私が正しければ、それは私のモバイル 3g ネットワークが TLS を台無しにしている可能性があるということですか、それとも何か他にすべきことはありますか?

DefaultHttpClientをサブクラス化し、サーバーの自己署名証明書を含むキーストアをインポートすることで、3g で動作させることができますが、それは私の好みのオプションではありません。

4

1 に答える 1

0

-servernameオプションを追加するとServer Name Indication、メッセージのフィールドが設定されるだけでClient Hello、ターゲットホストに多くの証明書が含まれている場合に、正しい証明書を選択するのに役立ちます。ただし、それは問題とは関係ありません。

SSL ハンドシェーク中に、証明書はサブジェクト/発行者のペアで配信され、証明書チェーンが形成されます。

つまりgoogle.com、証明書チェーンは次のようになります。

openssl s_client -connect google.com:443
CONNECTED(00000003)
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=*.google.com
   i:/C=US/O=Google Inc/CN=Google Internet Authority G2
 1 s:/C=US/O=Google Inc/CN=Google Internet Authority G2
   i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
 2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
   i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
---

受信すると、クライアントはチェーン内のすべての発行者を下から上 (ルート) に検証しようとします。クライアントがルート証明書を検証できなかった場合、 Trust anchor for certification path not foundメッセージが表示されます。

WiFi/3G の問題に戻ると、モバイル ネットワークの DNS が証明書チェーンの中間発行者のアドレスを解決できなかった可能性があります。

アップデート:

発行者の証明書を APK に入れTrustManager、コードに via を追加できます。このアプローチは、アクセス ネットワークの制限 (ある場合) を克服する可能性があります。

于 2015-08-27T22:44:17.710 に答える