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

Answers:


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 \安全性)和Jre(C:\ Program Files \ Java \ jre1.8.0_91 \ lib \ security)对我
有用

149

这是在macOS上对我可靠的方法。确保将example.com和443替换为您尝试连接的实际主机名和端口,并提供自定义别名。第一个命令从远程服务器下载提供的证书,并将其以x509格式保存在本地。第二条命令将保存的证书加载到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是什么,我需要提供一个.pem证书那在这里??
Vishnu Ranganathan

3
.crt和.pem是同一文件格式的常用文件扩展名。如果已经有了该文件,只需运行第二个命令并将其传递给-file参数即可。
·马丁·丹佩西

1
好东西。唯一的事情是:由于某种原因,我不得不使用最新的openssl 1.0.Xx,旧的9.X.Xx无法正常工作。
zbstof

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 cert终于开始工作了:

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


我遇到了同样的问题,这非常有用,但就我而言,您只需要将服务器证书添加到JDK版本的cacerts文件中
Pigritia,2017年

41
  1. 使用Firefox导出SSL证书。您可以通过在浏览器中单击URL来导出它,然后选择导出证书的选项。假设证书文件名为your.ssl.server.name.crt
  2. 转到您的JRE_HOME/binJDK/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

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
效果很好。我在连接外部API的Jenkins服务器上遇到错误,该错误更改了他的证书并使我的构建失败。这解决了我的问题
user9869932,2017年

Oracle首先应该提供这样的服务,否则,永远不要每个人都创建自己的可怕的SSL解决方案。SSL证书处理应该是操作系统的工作。
Wolfgang Fahl,

17

不再“无法找到到所需目标的有效认证路径”中引用

尝试使用JSSE打开与主机的SSL连接时。这通常意味着服务器正在使用测试证书(可能是使用keytool生成的),而不是来自知名商业证书颁发机构(例如Verisign或GoDaddy)的证书。在这种情况下,Web浏览器会显示警告对话框,但是由于JSSE无法假定存在交互式用户,因此默认情况下它只会引发异常。

证书验证是SSL安全性中非常重要的部分,但是我不会写此条目来解释细节。如果您有兴趣,可以先阅读Wikipedia Blur。如果您确实愿意,我正在编写此条目,以显示一种使用测试证书与该主机进行通信的简单方法。

基本上,您想使用受信任的证书将服务器的证书添加到KeyStore中

尝试那里提供的代码。这可能会有所帮助。


5
关于“证书验证是SSL安全性的非常重要的一部分”的部分不一定是正确的。SSL可为您提供两项保证:(1)您的通信是私人的,(2)您正在与NSA已知的服务器通信。(:-)有时,您只关心会话的隐私,然后自签名证书也可以。参见social-biz.org/2011/10/16/the-anti-ssl-conspiracy
AgilePro

@AgilePro SSL为您提供四项保证:身份验证,隐私,完整性和授权的可能性。它不能保证您正在与NSA已知的服务器通信。从字面上讲,只关心隐私而不进行身份验证是一个矛盾。
洛恩侯爵,

@EJP同意,如果您使用客户端证书,则可以进行身份​​验证,并且我认为可以进行授权...但是大多数用途不与客户端证书一起使用。您如何称呼“自签名”证书和签名机构的证书之间的区别?签名机构是否给予“正直”。我对国家安全局的笑话是,所有签署机构都不能积极保证与一切事物的独立性。确实不是那种偏执狂,但关键是您的证书仅是签名颁发机构可以做到的秘密。自签名可以更秘密。
AgilePro '16

@AgilePro使用服务器证书对服务器进行身份验证,并且需要使用SSL来确保SSL安全,如RFC 2246所述。证书根本不是秘密的:因此,其余意见毫无意义。
罗恩侯爵,

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)
        在sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1496)
        在sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
        在sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
        在sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
        在sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
        在sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
        在sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:747)
        在sun.security.ssl.AppOutputStream.write(AppOutputStream.java:123)
        在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是默认密码。最后提示“是否信任此证书?[no]:”,请提供“是”将证书添加到密钥库中。

验证:

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
乔纳斯BERGSTROM

我需要类似的东西@JonasBergström,您的SSLContext解决方案会有所帮助。
EnterSB 2014年

8
请注意,此解决方案是不安全的。
罗恩侯爵

谢谢乔纳斯,您的解决方案确实解决了问题。但是我发现创建第一个连接要花费很长时间(3-5s),之后每个连接只需要300-400 ms。
twcai

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

这也可能是由于将GoDaddy证书与使用SHA2签名的Java 7一起使用所致。

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之后,问题就消失了。rr

背景:./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应用程序。

解决方案:在AVG部分中输入“ Web和电子邮件”,然后禁用“电子邮件保护”。如果站点不安全,AVG将阻止证书。



2

有很多方法可以解决这个问题...

一种方法是在密钥库文件中设置TrustStore证书,并将其放在应用程序的路径中,然后在main方法中设置这些系统属性:

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

另一种方法是将密钥库作为资源文件放置在项目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

您有两个选择,将软件将运行的每个jvm的自签名证书导入到Java的密钥库中,或尝试使用非验证的ssl工厂:

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

1

像这样的图像有问题。

在此处输入图片说明

尝试了一些解决方案。但是发现即使是同一个项目,当它在另一个人的工作场所时,也完全可以。无需其他设置。因此,我们猜测这是一个环境问题。我们尝试更改JDK版本,IDE,但没有用。我们花了大约4个小时进行调查,直到我们尝试了评分最高的答案。我没有找到该答案中提到的错误,但是通过我的浏览器发现有关HTTP URL(锁定)的信息是Charles的认证。然后我意识到我的查尔斯一直在忙。只要我关闭它,它就可以正常工作。

因此,我留下了可能对您的案例有用的经验。


0

就我而言,我正在使用Java 1.6运行MacOs High Sierra。cacert文件的位置与上面Gabe Martin-Dempesy的答案中引用的位置不同。该cacert文件也已经链接到另一个位置(/ Library / Internet插件/JavaAppletPlugin.plugin/Contents/Home/lib/security/cacerts)。

使用FireFox,我将证书从有问题的网站导出到了名为“ 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

就我而言,我的密钥库和信任库都具有相同的证书,因此删除信任库会有所帮助。如果您有多个证书副本,有时证书链可能会成为问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.