foo.net
とbar.com
の2つのドメインがあります。どちらもSSL証明書を持っており、すべてのデスクトップブラウザとモバイルブラウザでうまく機能します。これらは、nginxで構成された同じサーバーでホストされます。
ただし、ネイティブAndroidアプリ内からドメインにリクエストを送信すると、どういうわけか間違ったドメインから証明書を取得します!これにより、IO例外:
request = new HttpPost("https://foo.net/api/v1/baz");
request.setHeader("Authorization", "user:pass");
response = httpClient.execute(request);
.。
javax.net.ssl.SSLException: hostname in certificate didn't match: <foo.net> != <bar.com> OR <bar.com> OR <www.bar.com>
サーバーが正しく構成されていることを他のすべての測定値が示しているように見える場合、Android/Javaがbar.com
からの証明書を使用しようとする原因は何ですか? nginxアクセスまたはエラーログには何も表示されません。私のAndroidプロジェクトのどこにもbar.com
についての言及はありません。
編集:理由はわかりませんが、サーバーがサーバーIP bar.com
のhttps://198.245.xx.xxx
の証明書を使用しているようです
この問題の原因として最も可能性が高いのは、サーバーが Server Name Indication を使用して送信する証明書を選択することです。クライアントがSNIをサポートしていない場合、サーバーはSSL/TLSハンドシェイク中に(HTTPトラフィックが送信される前に)送信する証明書を選択できません。 SNIは、同じIPアドレスとポートで複数の証明書を使用する場合に必要ですが、すべてのクライアントがSNIをサポートしているわけではありません(WindowsXPのすべてのバージョンと多数のモバイルブラウザーでIE )。
また、Apache HTTPクライアントライブラリを目に見えて使用しています(HttpsURLConnection
ではありません。 いくつかのAndroidバージョン でSNIサポートがあります。 Apache HTTPクライアントライブラリのSNI ごく最近 、そして確かにAndroidスタックには入っていません。
この記事で説明されている回避策 は便利です(ただし、Android 4.2+)でのみ機能するようです)。
別の2つのオプションは次のとおりです。
HttpsURLConnection
)を使用する。トリックのようなApacheのソリューション:SSL証明書は/ etc/Apache2/sites-enabledからの仮想ホスト名に基づいてロードされます。したがって、そのチェックをだますには、問題のある証明書が最初にロードされていることを確認してください(vhostは名前でロードされていることに注意してください)。
Foo.netの証明書が正しく構成されておらず、bar.comと同じホスト名を使用しているようです。
念のため、foo.netで https://www.digicert.com/help/ などのオンライン証明書検証ツールを実行してみてください。
Foo.netの証明書を正しいホスト名で再生成するか、ngixを再構成してnginxが正しいホストに正しい証明書を提供するようにする必要があると思います。