Java:sun.security.provider.certpath.SunCertPathBuilderException:要求されたターゲットへの有効な証明書パスが見つかりません


248

httpsサーバーからファイルをダウンロードするクラスがあります。実行すると、多くのエラーが返されます。証明書に問題があるようです。クライアントサーバー認証を無視することは可能ですか?もしそうなら、どうですか?

package com.da;

import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.CharBuffer;
import java.util.concurrent.Future;

import org.apache.http.HttpResponse;
import org.apache.http.client.utils.URIUtils;
import org.apache.http.impl.nio.client.DefaultHttpAsyncClient;
import org.apache.http.nio.IOControl;
import org.apache.http.nio.client.HttpAsyncClient;
import org.apache.http.nio.client.methods.AsyncCharConsumer;
import org.apache.http.nio.client.methods.HttpAsyncGet;
import org.apache.http.nio.client.methods.HttpAsyncPost;

public class RSDDownloadFile {
    static FileOutputStream fos;

    public void DownloadFile(String URI, String Request) throws Exception
    {
        java.net.URI uri = URIUtils.createURI("https", "176.66.3.69:6443", -1, "download.aspx",
                "Lang=EN&AuthToken=package", null);
        System.out.println("URI Query: " + uri.toString());

        HttpAsyncClient httpclient = new DefaultHttpAsyncClient();
        httpclient.start();
        try {
            Future<Boolean> future = httpclient.execute(
                    new HttpAsyncGet(uri),
                    new ResponseCallback(), null);

            Boolean result = future.get();
            if (result != null && result.booleanValue()) {
                System.out.println("\nRequest successfully executed");
            } else {
                System.out.println("Request failed");
            }              
        } 
        catch(Exception e){
            System.out.println("[DownloadFile] Exception: " + e.getMessage());
        }
        finally {
            System.out.println("Shutting down");
            httpclient.shutdown();
        }
        System.out.println("Done");  

    }

    static class ResponseCallback extends AsyncCharConsumer<Boolean> {

        @Override
        protected void onResponseReceived(final HttpResponse response) {
             System.out.println("Response: " + response.getStatusLine());
             System.out.println("Header: " + response.toString());
             try {   
                 //if(response.getStatusLine().getStatusCode()==200)
                     fos = new FileOutputStream( "Response.html" );
             }catch(Exception e){
                 System.out.println("[onResponseReceived] Exception: " + e.getMessage());
             }
        }

        @Override
        protected void onCharReceived(final CharBuffer buf, final IOControl ioctrl) throws IOException {
            try
            {
                while (buf.hasRemaining()) 
                {
                    //System.out.print(buf.get());
                    fos.write(buf.get());
                }
            }catch(Exception e)
            {
                System.out.println("[onCharReceived] Exception: " + e.getMessage());
            }
        }

        @Override
        protected void onCleanup() {
            try
            {             
                if(fos!=null)
                    fos.close();
            }catch(Exception e){
                System.out.println("[onCleanup] Exception: " + e.getMessage());         
            }
             System.out.println("onCleanup()");
        }

        @Override
        protected Boolean buildResult() {
            return Boolean.TRUE;
        }

    }
}

エラー:

URI Query: https://176.66.3.69:6443/download.aspx?Lang=EN&AuthToken=package
Aug 2, 2011 3:47:57 PM org.apache.http.impl.nio.client.NHttpClientProtocolHandler exception
SEVERE: I/O error: General SSLEngine problem
javax.net.ssl.SSLHandshakeException: General SSLEngine problem
    at com.sun.net.ssl.internal.ssl.Handshaker.checkThrown(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLEngineImpl.checkTaskThrown(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLEngineImpl.writeAppRecord(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLEngineImpl.wrap(Unknown Source)
    at javax.net.ssl.SSLEngine.wrap(Unknown Source)
    at org.apache.http.impl.nio.reactor.SSLIOSession.doHandshake(SSLIOSession.java:154)
    at org.apache.http.impl.nio.reactor.SSLIOSession.isAppInputReady(SSLIOSession.java:276)
    at org.apache.http.impl.nio.client.InternalClientEventDispatch.inputReady(InternalClientEventDispatch.java:79)
    at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:161)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:335)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315)
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:275)
    at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)
    at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:542)
    at java.lang.Thread.run(Unknown Source)
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLEngineImpl.fatal(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.net.ssl.internal.ssl.Handshaker$DelegatedTask.run(Unknown Source)
    at org.apache.http.impl.nio.reactor.SSLIOSession.doHandshake(SSLIOSession.java:180)
    ... 9 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.validator.PKIXValidator.doBuild(Unknown Source)
    at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
    at sun.security.validator.Validator.validate(Unknown Source)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
    at com.sun.net.ssl.internal.ssl.JsseX509TrustManager.checkServerTrusted(Unknown Source)
    ... 16 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
    at java.security.cert.CertPathBuilder.build(Unknown Source)
    ... 21 more
onCleanup()

[DownloadFile] Exception: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
Shutting down
Done

2
このエラーが発生してセキュリティチームに連絡したところ、チームが会社から提供された古いJARを使用していたため、使用しているJARにパッチを適用する必要がありました。同様の状況にある可能性のある他の人のための参考までに。
kayleeFrye_onDeck

回答:


215

サーバーに自己署名証明書がある場合、問題が発生します。これを回避するには、この証明書をJVMの信頼できる証明書のリストに追加します。

この記事では、ブラウザーから証明書をフェッチして、JVMのcacertsファイルに追加する方法について説明します。JAVA_HOME/jre/lib/security/cacertsファイルを編集するか、-Djavax.net.ssl.trustStoreパラメータを使用してアプリケーションを実行できます。多くの場合混乱の原因となるため、使用しているJDK / JREも確認してください。

参照:SSL証明書サーバー名の解決方法/ keytoolを使用して代替名を追加できますか?java.security.cert.CertificateException: No name matching localhost found例外が発生した場合。


3
これではうまくいきませんでした。ルートとチェーン証明書がインストールされていますが、Tomcat-7は、「リクエストされたターゲットへの有効な証明書パスが見つからない」ために発生したvalidatorExceptionを引き続き報告し、これをデバッグする方法はありますか?
Cheruvim

この問題は、信頼されていない誰かが署名した証明書でも発生します。
ローンの侯爵

すごい!できます!jreとjdkの両方を使用でき、両方をcacerts更新する必要があることを忘れないでください
Dima Fomin

私の場合、ルートCAはそこにありましたが、次にダウンしたCAはありませんでした。次のCAを追加するとうまくいきました-ありがとう。
java-addict301

1
私の場合、Netbeans + Apache Tomcat(統合)を使用しているので、.cerをJdk / jre(C:\ Program Files \ Java \ jdk1.8.0_152 \ jre \ lib \のトラストストア「cacerts」に追加します。 security)とJre(C:\ Program Files \ Java \ jre1.8.0_91 \ lib \ security)は私のために働く
Jnn

149

macOSで確実に機能するのは次のとおりです。example.comと443を、接続しようとしている実際のホスト名とポートに置き換えて、カスタムエイリアスを指定してください。最初のコマンドは、提供された証明書をリモートサーバーからダウンロードし、x509形式でローカルに保存します。2番目のコマンドは、保存された証明書をJavaのSSLトラストストアにロードします。

openssl x509 -in <(openssl s_client -connect example.com:443 -prexit 2>/dev/null) -out ~/example.crt
sudo keytool -importcert -file ~/example.crt -alias example -keystore $(/usr/libexec/java_home)/jre/lib/security/cacerts -storepass changeit

3
なぜ私のために働くのですか?説明を提供する必要があります。
ローンの侯爵

openssl x509 -in <(openssl s_client -connect example.com:443 -prexit 2> / dev / null)-out〜/ example.crt-コマンドのexample.crtとは何ですか。あれ?
Vishnu Ranganathan

3
.crtと.pemは、同じファイル形式で一般的に使用されるファイル拡張子です。ファイルが既にある場合は、2番目のコマンドを実行して、それを-file引数に渡します。
Gabe Martin-Dempesy 2017年

1
素晴らしいもの。唯一のことは、何らかの理由で最新のopenssl 1.0.Xxを使用する必要があり、古い9.X.Xxが機能していなかったことです。
zbstof 2017年

1
これはSNIエンドポイントでは機能しません。その場合は、次を追加する必要があります。-servername example.com証明書をフェッチするとき
Patrik Beck

46

symantecからの有効な署名されたワイルドカード証明書で同じ問題がありました。

まず、-Djavax.net.debug = SSL指定してJavaアプリケーションを実行して、実際に何が起こっているかを確認してください。

私は終わった中間証明書のインポート証明書チェーンが破損する原因となりました。

不足している中間証明書をsymantecからダウンロードしました(不足している証明書へのダウンロードリンクは、sslハンドシェイクログで確認できます。私の場合は、http://svrintl-g3-aia.verisign.com/SVRIntlG3.cerです)。

そして、証明書をJavaキーストアにインポートしました。中間証明書をインポートした後、私のワイルドカードssl証明書がようやく機能し始めました。

keytool -import -keystore ../jre/lib/security/cacerts -trustcacerts -alias "VeriSign Class 3 International Server CA - G3" -file /pathto/SVRIntlG3.cer

これは事実でした:
kisna

2
混乱を避けるために、デバッグパラメータを指定してjava(またはjcurl)を実行し、ログでリモートの「証明書チェーン」を確認してから、次のように(デフォルトではなく)明示的に渡されたトラストストアの「CN」をgrepします。存在しない場合は、追加する必要があります。ssllabs.com/ssltest/analyze.htmlは、サーバー側の証明書に不完全なチェーンがあり、追加する必要のある中間の証明書パス証明書が含まれているかどうかを示します。 -Djavax.net.debug=ssl,handshake -Djavax.net.ssl.keyStoreType=PKCS12 -Djavax.net.ssl.keyStore=our-client-certs -Djavax.net.ssl.trustStoreType=jks -Djavax.net.ssl.trustStore=their-server-certs
kisna 2017年


私は、これは非常に便利ですが、私の場合にはあなたが唯一のJDKバージョンのcacertsファイルにサーバー証明書を追加する必要がありました、同じ問題を持っていた
Pigritia

41
  1. Firefoxを使用してSSL証明書をエクスポートします。ブラウザーでURLをクリックして証明書をエクスポートし、証明書をエクスポートするオプションを選択できます。証明書のファイル名がyour.ssl.server.name.crtであるとしましょう
  2. JRE_HOME/binまたはに行くJDK/JRE/bin
  3. コマンドを入力してください
  4. keytool -keystore ..\lib\security\cacerts -import -alias your.ssl.server.name -file .\relative-path-to-cert-file\your.ssl.server.name.crt
  5. Javaプロセスを再起動します

13
パスワードを要求された場合は、デフォルトのcacerts鍵ストアのパスワードchangeitstackoverflow.com/a/22782035/1304830)を使用します。また、必ず管理者としてcmdを実行してください。
Fr4nz 2016

22

@Gabe Martin-Dempesyの答えは私に役立ちます。そして、それに関連する小さなスクリプトを書きました。使い方はとても簡単です。

ホストから証明書をインストールします。

> sudo ./java-cert-importer.sh example.com

すでにインストールされている証明書を削除します。

> sudo ./java-cert-importer.sh example.com --delete

java-cert-importer.sh

#!/usr/bin/env bash

# Exit on error
set -e

# Ensure script is running as root
if [ "$EUID" -ne 0 ]
  then echo "WARN: Please run as root (sudo)"
  exit 1
fi

# Check required commands
command -v openssl >/dev/null 2>&1 || { echo "Required command 'openssl' not installed. Aborting." >&2; exit 1; }
command -v keytool >/dev/null 2>&1 || { echo "Required command 'keytool' not installed. Aborting." >&2; exit 1; }

# Get command line args
host=$1; port=${2:-443}; deleteCmd=${3:-${2}}

# Check host argument
if [ ! ${host} ]; then
cat << EOF
Please enter required parameter(s)

usage:  ./java-cert-importer.sh <host> [ <port> | default=443 ] [ -d | --delete ]

EOF
exit 1
fi;

if [ "$JAVA_HOME" ]; then
    javahome=${JAVA_HOME}
elif [[ "$OSTYPE" == "linux-gnu" ]]; then # Linux
    javahome=$(readlink -f $(which java) | sed "s:bin/java::")
elif [[ "$OSTYPE" == "darwin"* ]]; then # Mac OS X
    javahome="$(/usr/libexec/java_home)/jre"
fi

if [ ! "$javahome" ]; then
    echo "WARN: Java home cannot be found."
    exit 1
elif [ ! -d "$javahome" ]; then
    echo "WARN: Detected Java home does not exists: $javahome"
    exit 1
fi

echo "Detected Java Home: $javahome"

# Set cacerts file path
cacertspath=${javahome}/lib/security/cacerts
cacertsbackup="${cacertspath}.$$.backup"

if ( [ "$deleteCmd" == "-d" ] || [ "$deleteCmd" == "--delete" ] ); then
    sudo keytool -delete -alias ${host} -keystore ${cacertspath} -storepass changeit
    echo "Certificate is deleted for ${host}"
    exit 0
fi

# Get host info from user
#read -p "Enter server host (E.g. example.com) : " host
#read -p "Enter server port (Default 443) : " port

# create temp file
tmpfile="/tmp/${host}.$$.crt"

# Create java cacerts backup file
cp ${cacertspath} ${cacertsbackup}

echo "Java CaCerts Backup: ${cacertsbackup}"

# Get certificate from speficied host
openssl x509 -in <(openssl s_client -connect ${host}:${port} -prexit 2>/dev/null) -out ${tmpfile}

# Import certificate into java cacerts file
sudo keytool -importcert -file ${tmpfile} -alias ${host} -keystore ${cacertspath} -storepass changeit

# Remove temp certificate file
rm ${tmpfile}

# Check certificate alias name (same with host) that imported successfully
result=$(keytool -list -v -keystore ${cacertspath} -storepass changeit | grep "Alias name: ${host}")

# Show results to user
if [ "$result" ]; then
    echo "Success: Certificate is imported to java cacerts for ${host}";
else
    echo "Error: Something went wrong";
fi;

完璧に動作します。よくやった!。これが機能する方法です。SSLサービスを開始し(実行されていない場合)、説明されているようにコマンドを実行します(例:)./java-cert-importer.sh example.com 1234。それでおしまい。
lepe

1
よく働く。Jenkinsサーバーが外部APIに接続しているときにエラーが発生し、証明書が変更され、ビルドが失敗しました。これは私の問題を解決します
user9869932

オラクルはそもそもこのようなものを提供する必要がありましたが、誰もが独自の恐ろしいSSLソリューションを作成したことは決してありませんでした。SSL証明書の処理は、オペレーティングシステムの仕事である必要があります。
Wolfgang Fahl

17

「要求されたターゲットへの有効な証明書パスが見つかりません」からの引用

JSSEを使用してホストへのSSL接続を開こうとしたとき。これが通常意味することは、サーバーがVerisignやGoDaddyなどのよく知られた商用認証局からの証明書ではなく、(おそらくkeytoolを使用して生成された)テスト証明書を使用していることです。この場合、Webブラウザーは警告ダイアログを表示しますが、JSSEは対話ユーザーが存在すると想定できないため、デフォルトで例外をスローするだけです。

証明書の検証はSSLセキュリティの非常に重要な部分ですが、詳細を説明するためにこのエントリを記述しているわけではありません。興味がある場合は、ウィキペディアの宣伝文を読むことから始めてください。このエントリは、本当に必要な場合に、テスト証明書を使用してそのホストと対話する簡単な方法を示すために作成しています。

基本的に、信頼できる証明書を使用してサーバーの証明書をキーストアに追加します

そこで提供されているコードを試してください。役立つかもしれません。


5
「証明書の検証はSSLセキュリティの非常に重要な部分です」という部分は必ずしも正しくありません。SSLは2つの保証を提供します:(1)通信がプライベートであること、および(2)NSAが認識しているサーバーと通信していること(:-)場合によっては、会話のプライバシーのみを気にし、自己署名証明書で結構です。social-biz.org/2011/10/16/the-anti-ssl-conspiracyを
AgilePro

@AgilePro SSLは、認証、プライバシー、完全性、および許可の可能性という4つの保証を提供します。NSAが認識しているサーバーと通信しているという保証はありませ。認証なしでプライバシーのみを気にすることは、言葉で矛盾します。
ローンの侯爵

@EJPクライアント証明書を使用すると認証を取得でき、認可の可能性があると思いますが、ほとんどの用途はクライアント証明書ではありません。「自己署名」証明書と署名機関からの証明書の違いは何ですか。署名機関は「完全性」を与えますか。NSAについての私の冗談は、すべての署名当局がすべてからの独立を積極的に保証することはできないということです。それほど妄想的ではありませんが、要点は、証明書は署名機関が作成できるほど秘密にされていることです。自己署名はより秘密にすることができます。
AgilePro 2016年

@AgilePro サーバー証明書の使用はサーバーを認証し、RFC 2246に記載されているようにSSLを安全にするために必要です。証明書はまったく秘密ではないため、コメントの残りの部分は意味がありません。
ローン侯爵

6

これは私の問題を解決しました、

証明書をローカルJavaにインポートする必要があります。そうでない場合、以下の例外が発生する可能性があります。

    javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIXパスの構築に失敗しました:sun.security.provider.certpath.SunCertPathBuilderException:要求されたターゲットへの有効な証明書パスが見つかりません
        sun.security.ssl.Alerts.getSSLException(Alerts.java:192)で
        sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)で
        sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)で

SSLPOKEは、ローカルマシンからhttps接続をテストできるツールです。

接続をテストするコマンド:

"%JAVA_HOME%/bin/java" SSLPoke <hostname> 443
    sun.security.validator.ValidatorException:PKIXパスの構築に失敗しました: 
    sun.security.provider.certpath.SunCertPathBuilderException:要求されたターゲットへの有効な証明書パスが見つかりません
        sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)で
        sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)で
        sun.security.validator.Validator.validate(Validator.java:260)で
        sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)で
        sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)で
        sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)で
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1496)
        sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)で
        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
        at sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
        sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)で
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
        sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:747)で
        at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123)
        at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:138)
        SSLPoke.main(SSLPoke.java:31)で
    原因:sun.security.provider.certpath.SunCertPathBuilderException:への有効な証明書パスが見つかりません 
    要求されたターゲット
        sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)で
        sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
        java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)で
        sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)で
        ...さらに15
keytool -import -alias <anyname> -keystore "%JAVA_HOME%/jre/lib/security/cacerts" -file <cert path>

これにより、最初に「キーストアのパスワードを入力してください」というプロンプトが表示されchangeitます。これがデフォルトのパスワードです。最後に、「Trust this certificate?[no]:」というプロンプトが表示されたら、「yes」を入力して証明書をキーストアに追加します。

検証:

C:\tools>"%JAVA_HOME%/bin/java" SSLPoke <hostname> 443
Successfully connected    

5

コードでのみ機能させることができました。つまり、keytoolを使用する必要はありません。

import com.netflix.config.DynamicBooleanProperty;
import com.netflix.config.DynamicIntProperty;
import com.netflix.config.DynamicPropertyFactory;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.apache.http.nio.conn.NoopIOSessionStrategy;
import org.apache.http.nio.conn.SchemeIOSessionStrategy;
import org.apache.http.nio.conn.ssl.SSLIOSessionStrategy;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public class Test
{
    private static final DynamicIntProperty MAX_TOTAL_CONNECTIONS = DynamicPropertyFactory.getInstance().getIntProperty("X.total.connections", 40);
    private static final DynamicIntProperty ROUTE_CONNECTIONS = DynamicPropertyFactory.getInstance().getIntProperty("X.total.connections", 40);
    private static final DynamicIntProperty CONNECT_TIMEOUT = DynamicPropertyFactory.getInstance().getIntProperty("X.connect.timeout", 60000);
    private static final DynamicIntProperty SOCKET_TIMEOUT = DynamicPropertyFactory.getInstance().getIntProperty("X.socket.timeout", -1);
    private static final DynamicIntProperty CONNECTION_REQUEST_TIMEOUT = DynamicPropertyFactory.getInstance().getIntProperty("X.connectionrequest.timeout", 60000);
    private static final DynamicBooleanProperty STALE_CONNECTION_CHECK = DynamicPropertyFactory.getInstance().getBooleanProperty("X.checkconnection", true);

    public static void main(String[] args) throws Exception
    {

        SSLContext sslcontext = SSLContexts.custom()
                .useTLS()
                .loadTrustMaterial(null, new TrustStrategy()
                {
                    @Override
                    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException
                    {
                        return true;
                    }
                })
                .build();
        SSLIOSessionStrategy sslSessionStrategy = new SSLIOSessionStrategy(sslcontext, new AllowAll());

        Registry<SchemeIOSessionStrategy> sessionStrategyRegistry = RegistryBuilder.<SchemeIOSessionStrategy>create()
                .register("http", NoopIOSessionStrategy.INSTANCE)
                .register("https", sslSessionStrategy)
                .build();

        DefaultConnectingIOReactor ioReactor = new DefaultConnectingIOReactor(IOReactorConfig.DEFAULT);
        PoolingNHttpClientConnectionManager connectionManager = new PoolingNHttpClientConnectionManager(ioReactor, sessionStrategyRegistry);
        connectionManager.setMaxTotal(MAX_TOTAL_CONNECTIONS.get());
        connectionManager.setDefaultMaxPerRoute(ROUTE_CONNECTIONS.get());

        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(SOCKET_TIMEOUT.get())
                .setConnectTimeout(CONNECT_TIMEOUT.get())
                .setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT.get())
                .setStaleConnectionCheckEnabled(STALE_CONNECTION_CHECK.get())
                .build();

        CloseableHttpAsyncClient httpClient = HttpAsyncClients.custom()
                .setSSLStrategy(sslSessionStrategy)
                .setConnectionManager(connectionManager)
                .setDefaultRequestConfig(requestConfig)
                .build();

        httpClient.start();

        // use httpClient...
    }

    private static class AllowAll implements X509HostnameVerifier
    {
        @Override
        public void verify(String s, SSLSocket sslSocket) throws IOException
        {}

        @Override
        public void verify(String s, X509Certificate x509Certificate) throws SSLException {}

        @Override
        public void verify(String s, String[] strings, String[] strings2) throws SSLException
        {}

        @Override
        public boolean verify(String s, SSLSession sslSession)
        {
            return true;
        }
    }
}

1
ところで、私はhttpasyncclient使用しています:4.0.1
ジョナス・バーグストロム

同様のものが必要でした、@JonasBergström、SSLContextを使用したソリューションは非常に役立ちます。
EnterSBは2014年

8
このソリューションは安全ではないことに注意してください。
ローン侯爵

Jonasに感謝します。あなたの解決策は問題を解決しました。しかし、最初の接続を作成するのに非常に長い時間(3〜5秒)がかかり、その後、すべての接続に300〜400ミリ秒しか必要ないことがわかりました。
twcai 2015年

5

私のApache 2.4インスタンス(Comodoワイルドカード証明書を使用)でのこのエラーの原因は、SHA-1署名済みルート証明書への不完全なパスでした。発行された証明書に複数のチェーンがあり、SHA-1ルート証明書に至るチェーンに中間証明書がありませんでした。最新のブラウザーはこれを処理する方法を知っていますが、Java 7はデフォルトでは処理しません(コードでこれを実行するための複雑な方法はいくつかあります)。結果は、自己署名証明書の場合と同じように見えるエラーメッセージです。

Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:196)
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:268)
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380)
    ... 22 more

この場合、中間証明書が見つからないため、「要求されたターゲットへの有効な証明書パスが見つかりません」というメッセージが生成されます。サーバーに対してSSL Labsテストを使用して、欠落している証明書を確認できます。適切な証明書を見つけたら、それをダウンロードし、(サーバーが管理下にある場合は)証明書バンドルに追加します。または、不足している証明書をローカルにインポートすることもできます。サーバーでこの問題に対応することは、問題に対するより一般的な解決策です。


ssllabs.com/ssltestは救世主です。それを有効な証明書の検証と比較するだけです。
kisna 16

5

Windowsの場合のみ、次の手順に従います。

  1. Chromeで[設定]に移動します。
  2. [設定]で、[詳細設定を表示]をクリックします。
  3. HTTPS / SSLの下で、証明書の管理をクリックします。
  4. 証明書をエクスポートします。
  5. Windows検索(キーボードのWindowsキーを押す)では、javaと入力します。
  6. (Javaの設定)オプションを選択すると、Javaコントロールパネルが開きます
  7. Javaコントロールパネルの[セキュリティ]タブを選択します。
  8. [証明書の管理]を選択します
  9. インポートをクリックします
  10. (ユーザー)タブが選択され、証明書の種類が(信頼された証明書)である
  11. インポートボタンをクリックし、ダウンロードした証明書を参照してインポートします。

4

DebianとプリパッケージされたJavaが好きな人のために:

sudo mkdir /usr/share/ca-certificates/test/  # don't mess with other certs
sudo cp ~/tmp/test.loc.crt /usr/share/ca-certificates/test/
sudo dpkg-reconfigure --force ca-certificates  # check your cert in curses GUI!
sudo update-ca-certificates --fresh --verbose

以下を確認/etc/default/cacertsすることを忘れないでください。

# enable/disable updates of the keystore /etc/ssl/certs/java/cacerts
cacerts_updates=yes

証明書を削除するには:

sudo rm /usr/share/ca-certificates/test/test.loc.crt
sudo rm /etc/ssl/certs/java/cacerts
sudo update-ca-certificates --fresh --verbose

2

これは、SHA2を使用して署名されたJava 7でGoDaddy証明書を使用することによっても発生する可能性があります。

Chromeと他のすべてのブラウザは、安全性が低いため、SHA1を使用して署名されたSSL証明書のサポートを終了しています。

この問題の詳細と、サーバーで解決する必要がある場合の解決方法については、こちらをご覧ください。


2

証明書エラーでも同じ問題があり、SNIが原因でした。使用したhttpクライアントにはSNIが実装されていませんでした。したがって、バージョンの更新でうまくいきました

   <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.3.6</version>
    </dependency>

2

更新:再起動が助けになったのは偶然でした(私はそう願っていました!)問題の本当の原因は次のとおりです。Gradleが特定のキーストアを使用するように指示されている場合、そのキーストアにはすべての公式ルート証明書も含まれている必要があります。そうしないと、通常のリポジトリからライブラリにアクセスできません。私がしなければならなかったことはこれでした:

自己署名証明書をインポートします。

keytool -import -trustcacerts -alias myselfsignedcert -file /Users/me/Desktop/selfsignedcert.crt -keystore ./privateKeystore.jks

公式のルート証明書を追加します。

keytool -importkeystore -srckeystore <java-home>/lib/security/cacerts -destkeystore ./privateKeystore.jks

Gradleデーモンも邪魔になっているのかもしれません。./gradlew --status物事が荒々しく見え始めたら、見つかった実行中のすべてのデーモンを殺す価値があるかもしれません。

元の投稿:

誰もこれを信じないでしょう、私は知っています。それでも、他のすべてが失敗する場合は、試してみてください。問題が解決し。Macを再起動すると問題は解決しました。うん。

背景:./gradlew jarで「リクエストされたターゲットへの有効な証明書パスが見つからない」というメッセージが表示され続ける

ブラウザから保存され、privateKeystore.jksにインポートされた自己署名証明書で立ち往生しています。次に、GradleにprivateKeystore.jksを使用するように指示しました。

org.gradle.jvmargs=-Djavax.net.debug=SSL -Djavax.net.ssl.trustStore="/Users/me/IntelliJ/myproject/privateKeystore.jks"  -Djavax.net.ssl.trustStorePassword=changeit

前述のように、これは再起動後にのみ機能しました。


2

AVGバージョン18.1.3044(Windows 10を使用)は、ローカルのSpringアプリケーションを妨害します。

解決策:「Webおよび電子メール」と呼ばれるAVGセクションに入力し、「電子メール保護」を無効にします。サイトが安全でない場合、AVGは証明書をブロックします。



2

これを解決する方法はたくさんあります...

1つの方法は、TrustStore証明書をキーストアファイルに設定し、それをアプリケーションのパスに配置し、これらのシステムプロパティをメインメソッドで設定することです。

public static void main(String[] args) {
  System.setProperty("javax.net.ssl.trustStore", "trust-store.jks");
  System.setProperty("javax.net.ssl.trustStorePassword", "TrustStore");
  ...
}

もう1つの方法は、プロジェクトのjarファイル内にリソースファイルとしてキーストアを配置してロードする方法です。

public static SSLContext createSSLContext(String resourcePath, String pass) throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException, UnrecoverableKeyException, KeyManagementException {
  // initialise the keystore
  final char[] password = pass.toCharArray();
  KeyStore ks = KeyStore.getInstance("JKS");
  ks.load(ThisClass.class.getResourceAsStream(resourcePath
  ), password);

  // Setup the key manager factory.
  KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
  kmf.init(ks, password);

  // Setup the trust manager factory.
  TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
  tmf.init(ks);

  SSLContext sslc = SSLContext.getInstance("TLS");
  sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
  return sslc;
}

public static void main(String[] args) {
  SSLContext.setDefault(
    createSSLContext("/trust-store.jks", "TrustStore"));
  ...
}

Windowsでもこのソリューションを試すことができます:https : //stackoverflow.com/a/59056537/980442


.crtこの方法で、認証局のCA ファイルからキーストアファイルを作成しました。

keytool -import -alias ca -keystore trust-store.jks -storepass TrustStore -trustcacerts -file ca.crt

参考までに:https : //docs.oracle.com/javadb/10.8.3.0/adminguide/cadminsslclient.html


1

2つのオプションがあります。ソフトウェアが実行される各jvmのJavaのキーストアに自己署名証明書をインポートするか、非検証のsslファクトリを試します。

jdbc:postgresql://myserver.com:5432/mydatabasename?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory

1

この画像のような問題がありました。

ここに画像の説明を入力してください

いくつかの解決策を試しました。しかし、同じプロジェクトであっても、他の人の職場にいるときはまったく問題ないことがわかりました。追加の設定は必要ありません。だから私たちはそれが環境の問題だと推測しました。JDKバージョン、IDEを変更しようとしましたが、機能しませんでした。評価の高い回答を試すまで、調査には約4時間かかりました。その回答に記載されているエラーは見つかりませんでしたが、ブラウザを介してHTTP URL(ロック)についてチャールズの認証があることがわかりました。それから私は私のチャールズがいつもオンであることに気づきました。それをオフにしてさえいれば、問題なく動作しています。

だからあなたのケースに役立つかもしれない私の経験を残しました。


0

私の場合、Java 1.6でMacOs High Sierraを実行しています。cacertファイルは、上記のGabe Martin-Dempesyの回答で参照されている場所とは別の場所にあります。cacertファイルは、すでに別の場所(/ライブラリ/ Internet Plug-Ins / JavaAppletPlugin.plugin / Contents / Home / lib / security / cacerts)にもリンクされています。

FireFoxを使用して、問題のWebサイトから「exportedCertFile.crt」というローカルファイルに証明書をエクスポートしました。そこから、keytoolを使用して証明書をcacertファイルに移動しました。これで問題が解決しました。

bash-3.2# cd /Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/lib/security/
bash-3.2# keytool -importcert -file ~/exportedCertFile.crt -alias example -keystore cacerts -storepass changeit

0

最初にssl証明書をダウンロードしてから、java binパスに移動して、コンソールで以下のコマンドを実行します。

C:\java\JDK1.8.0_66-X64\bin>keytool -printcert -file C:\Users\lova\openapi.cer -keystore openapistore

-1

私の場合、キーストアとトラストストアの両方が同じ証明書を持っているので、トラストストアを削除すると役立ちました。証明書のコピーが複数ある場合、証明書のチェーンが問題になることがあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.