HTTPで正常に動作していますが、HTTPSソースを使用しようとすると、次の例外がスローされます。
10-12 13:22:11.169: WARN/System.err(332): javax.net.ssl.SSLHandshakeException: Java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
10-12 13:22:11.179: WARN/System.err(332): at org.Apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.Java:477)
10-12 13:22:11.179: WARN/System.err(332): at org.Apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.Java:328)
10-12 13:22:11.179: WARN/System.err(332): at org.Apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.setupSecureSocket(HttpConnection.Java:185)
10-12 13:22:11.179: WARN/System.err(332): at org.Apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.Java:433)
10-12 13:22:11.189: WARN/System.err(332): at org.Apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl$HttpsEngine.makeConnection(HttpsURLConnectionImpl.Java:378)
10-12 13:22:11.189: WARN/System.err(332): at org.Apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.Java:205)
10-12 13:22:11.189: WARN/System.err(332): at org.Apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.Java:152)
10-12 13:22:11.189: WARN/System.err(332): at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.Java:377)
10-12 13:22:11.189: WARN/System.err(332): at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.Java:364)
10-12 13:22:11.189: WARN/System.err(332): at org.jsoup.helper.HttpConnection.execute(HttpConnection.Java:143)
関連するコードは次のとおりです。
try {
doc = Jsoup.connect("https url here").get();
} catch (IOException e) {
Log.e("sys","coudnt get the html");
e.printStackTrace();
}
正しい方法で実行したい場合、および/または1つのサイトのみを処理する必要がある場合は、基本的には問題のWebサイトのSSL証明書を取得し、Javaキーストアにインポートする必要があります。 。これにより、Jsoup(またはJava.net.URLConnection
)を使用する前にSSLトラストストアとして設定したJKSファイルが生成されます。
Webブラウザーのストアから証明書を取得できます。 Firefoxを使用しているとします。
これでweb2.uconn.edu.crt
ファイルができました。
次に、コマンドプロンプトを開き、keytool
コマンドを使用してJavaキーストアにインポートします(JREの一部です)。
keytool -import -v -file /path/to/web2.uconn.edu.crt -keystore /path/to/web2.uconn.edu.jks -storepass drowssap
-file
は、ダウンロードした.crt
ファイルの場所を指す必要があります。 -keystore
は、生成された.jks
ファイル(SSLトラストストアとして設定するファイル)の場所を指す必要があります。 -storepass
は必須です。6文字以上であれば、任意のパスワードを入力できます。
これで、web2.uconn.edu.jks
ファイルができました。次のように、接続する前に最終的にSSLトラストストアとして設定できます。
System.setProperty("javax.net.ssl.trustStore", "/path/to/web2.uconn.edu.jks");
Document document = Jsoup.connect("https://web2.uconn.edu/driver/old/timepoints.php?stopid=10").get();
// ...
まったく異なる代替手段として、特に複数のサイトを処理する必要がある場合(つまり、World Wide Webクローラーを作成している場合)、すべてのSSL証明書を盲目的に信頼するようにJsoup(基本的にはJava.net.URLConnection
)に指示することもできます。この回答の最下部にあるセクション「信頼されていない、または誤って構成されたHTTPSサイトに対処する」も参照してください。 Java.net.URLConnectionを使用してHTTPリクエストを起動および処理する
私の場合、接続に.validateTLSCertificates(false)を追加するだけで済みました
Document doc = Jsoup.connect(httpsURLAsString)
.timeout(60000).validateTLSCertificates(false).get();
読み取りタイムアウトも増やす必要がありましたが、これは無関係です
ここでの回答と検索のリンクされた質問に出くわし、2つの情報を追加したいと思います。受け入れられた回答は私の非常に類似したシナリオに適合しないためですが、その場合にも当てはまる追加の解決策があります(証明書およびホスト名がテストシステムと一致しません)。
disableSSLCertCheck()
でラップしました。この方法を使用する前に、そこで行うことを確実に理解しておく必要があります。SSL証明書をチェックしないのは本当に愚かなことです。一般に受け入れられているCAによって署名されているサーバーには、常に正しいSSL証明書を使用してください。一般に受け入れられているCAを購入する余裕がない場合でも、上記の@BalusCで受け入れられた回答を使用して正しいSSL証明書を使用してください。正しいSSL証明書を構成できない場合(本番環境では当てはまりません)、次の方法が機能します。
private void disableSSLCertCheck() throws NoSuchAlgorithmException, KeyManagementException {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
public Java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
// Install the all-trusting trust manager
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new Java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting Host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// Install the all-trusting Host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
}
そのソリューション以来:
Document doc = Jsoup.connect(httpsURLAsString)
.timeout(60000).validateTLSCertificates(false).get();
非推奨の警告が表示され、間もなく削除されます。ここでは代替オプション(基本的には answer で提案されているのと同じアイデア)を使用しますが、特定のJSoup接続での証明書の警告を抑制します。
Kotlin
val document = Jsoup.connect("url")
.sslSocketFactory(socketFactory())
.get()
private fun socketFactory(): SSLSocketFactory {
val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
@Throws(CertificateException::class)
override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {
}
@Throws(CertificateException::class)
override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {
}
override fun getAcceptedIssuers(): Array<X509Certificate> {
return arrayOf()
}
})
try {
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, trustAllCerts, Java.security.SecureRandom())
return sslContext.socketFactory
} catch (e: Exception) {
when (e) {
is RuntimeException, is KeyManagementException -> {
throw RuntimeException("Failed to create a SSL socket factory", e)
}
else -> throw e
}
}
}
Java
Document document = Jsoup.connect("url")
.sslSocketFactory(socketFactory())
.get();
private SSLSocketFactory socketFactory() {
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
public Java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}};
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustAllCerts, new Java.security.SecureRandom());
return sslContext.getSocketFactory();
} catch (NoSuchAlgorithmException | KeyManagementException e) {
throw new RuntimeException("Failed to create a SSL socket factory", e);
}
}
NB。前述のように、証明書を無視することは良い考えではありません。
私は同じ問題を抱えていましたが、怠惰なルートを取りました-証明書を無視してとにかく続行するようにアプリに指示してください。
私はここからコードを取得しました: JavaでローカルHTTPS URLを使用するにはどうすればよいですか?
これを機能させるには、これらのクラスをインポートする必要があります。
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
接続を確立しようとする前にそのメソッドをどこかで実行するだけで、証明書を信頼します。もちろん、実際に証明書が本物であることを確認したい場合は役に立ちませんが、自分の内部Webサイトなどを監視するのに適しています。
この問題は開発環境でのみ発生しました。それを解決する解決策は、VMへのSSLを無視するいくつかのフラグを追加することでした:
-Ddeployment.security.TLSv1.1=false
-Ddeployment.security.TLSv1.2=false
私はこの分野の専門家ではありませんが、Java.net APIを使用してHTTPS経由でWebサイトに接続しようとしたときに、同様の例外に遭遇しました。 HTTPSを使用してサイトにアクセスすると、ブラウザーはSSL証明書に関して多くの作業を行います。ただし、手動で(HTTP要求を使用して)サイトに接続している場合でも、すべての作業を実行する必要があります。今、この作業の正確な内容はわかりませんが、証明書をダウンロードし、Javaがそれらを見つけることができる場所に置くことと関係があります。うまくいけば、あなたを正しい方向に向けるリンクがあります方向。
http://confluence.atlassian.com/display/JIRA/Connecting+to+SSL+services
Jsoupで同じ問題に直面していましたが、接続してhttpsのURLのドキュメントを取得できませんでしたが、JDKのバージョンを1.7から1.8に変更すると、問題は解決しました。
それはあなたを助けるかもしれません:)