首页 文章

解决javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX路径构建失败错误?

提问于
浏览
316

Edit :- 试图以更加流畅的方式格式化问题并接受答案 Blog

这是原始问题: -

我收到了这个错误

详细消息sun.security.validator.ValidatorException:PKIX路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到所请求目标的有效证书路径导致javax.net.ssl.SSLHandshakeException:sun.security.validator . ValidatorException:PKIX路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到所请求目标的有效证书路径

我使用tomcat 6作为网络服务器 . 我有两个https webbapplication安装在不同的tomcat上的differte端口,但在同一台机器上 . 说 App1(port 8443)App2(port 443) . App1 连接到 App2 . 当 App1 连接到 App2 i 时出现以上错误 . 我知道这是非常常见的错误,所以在不同的论坛和网站上遇到了很多解决方案 . 我在tomcat的 server.xml 下面有条目,即

keystoreFile="c:/.keystore" 
keystorePass="changeit"

每个站点都说同样的原因,即app2提供的证书不在app1 jvm的可信存储中 . 这似乎也是如此,当我厌倦了在IE浏览器中访问相同的URL,它的工作原理(温暖,这个网站的安全证书存在问题 . 这里我说继续这个网站)但是当相同的网址遭到打击时java客户端(在我的例子中) . 所以我得到了上述错误 . 所以把它放在trustore我尝试了这些树选项,即

Option1

System.setProperty("javax.net.ssl.trustStore", "C:/.keystore");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

Option2 在环境变量中设置如下

CATALINA_OPTS -- param name
-Djavax.net.ssl.trustStore=C:\.keystore -Djavax.net.ssl.trustStorePassword=changeit ---param value

Option3 在环境变量中设置如下

JAVA_OPTS -- param name
-Djavax.net.ssl.trustStore=C:\.keystore -Djavax.net.ssl.trustStorePassword=changeit ---param value

But nothing worked .

What at last worked 正在执行Pascal Thivent在How to handle invalid SSL certificates with Apache HttpClient?中建议的java方法,即执行程序InstallCert .

But this approach is fine for devbox setup but i can not use it at production environment.

我想知道为什么当我在 app2 服务器的 server.xml 中提到相同的值并且通过设置在truststore中的相同值时,上面提到的三种方法都不起作用

System.setProperty("javax.net.ssl.trustStore", "C:/.keystore") and System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

app1 计划中 .

有关更多信息,这是我如何 Build 连接

URL url = new URL(urlStr);

URLConnection conn = url.openConnection();

if (conn instanceof HttpsURLConnection) {

  HttpsURLConnection conn1 = (HttpsURLConnection) url.openConnection();

  conn1.setHostnameVerifier(new HostnameVerifier() {
    public boolean verify(String hostname, SSLSession session) {
      return true;
    }
  });

  reply.load(conn1.getInputStream());

14 回答

  • 28

    另一个原因可能是JDK的过时版本 . 我使用的是jdk版本1.8.0_60,只需更新到最新版本即可解决证书问题 .

  • 2

    下面的代码适用于我:

    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    
    import javax.net.ssl.X509TrustManager;
    
    public class TrustAnyTrustManager implements X509TrustManager {
    
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }
    
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }
    
    public X509Certificate[] getAcceptedIssuers() {
    return new X509Certificate[] {};
    }
    }
    

    HttpsURLConnection conn = null;
                URL url = new URL(serviceUrl);
                conn = (HttpsURLConnection) url.openConnection();
                 SSLContext sc = SSLContext.getInstance("SSL");  
                 sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom());  
    
                 conn.setSSLSocketFactory(sc.getSocketFactory());
    
  • 0

    它是Java的一个缺陷,没有使用像MacOS X那样的标准操作系统密钥库 . 我今天提交了一个更改请求,请参阅http://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8185892

  • 4

    对我来说,这个错误在尝试连接到处理SSL的NGINX反向代理后面的进程时也出现了 .

    原来问题是证书没有连接整个证书链 . 当我添加中间证书时,问题就解决了 .

    希望这可以帮助 .

  • 324

    您需要将 App2 的证书添加到位于 %JAVA_HOME%\lib\security\cacerts 的已使用JVM的信任库文件中 .

    首先,您可以通过运行以下命令来检查您的证书是否已在信任库中: keytool -list -keystore "%JAVA_HOME%/jre/lib/security/cacerts" (您无需提供密码)

    如果缺少证书,可以通过浏览器下载证书并使用以下命令将其添加到信任库:

    keytool -import -noprompt -trustcacerts -alias <AliasName> -file <certificate> -keystore <KeystoreFile> -storepass <Password>

    在导入之后,您可以再次运行第一个命令来检查您的证书是否已添加 .

    可以找到Sun / Oracle信息here .

  • 2

    javax.net.ssl.SSLHandshakeException:sun.security.validator.ValidatorException:PKIX路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到所请求目标的有效证书路径

    •当我收到错误时,我试图谷歌表达式的含义,我发现,当服务器更改其HTTPS SSL证书时,会出现此问题,而我们的旧版本的java无法识别根证书颁发机构(CA) .

    •如果您可以在浏览器中访问HTTPS URL,则可以更新Java以识别根CA.

    •在浏览器中,转到Java无法访问的HTTPS URL . 单击HTTPS证书链(Internet Explorer中有锁定图标),单击锁定以查看证书 .

    •转到证书的“详细信息”和“复制到文件” . 以 Base64 (.cer) 格式复制它 . 它将保存在您的桌面上 .

    •安装证书,忽略所有警报 .

    •这是我收集我尝试访问的URL的证书信息的方式 .

    现在我不得不让我的java版本知道证书,以便进一步拒绝识别URL . 在这方面,我必须提一下,我在谷歌的 \jre\lib\security 位置默认保留根证书信息,并且访问的默认密码是: changeit.

    要查看cacerts信息,请遵循以下步骤:

    •单击“开始”按钮 - >“运行”

    •键入cmd . 命令提示符将打开(您可能需要以管理员身份打开它) .

    •转到 Java/jreX/bin 目录

    •键入以下内容

    keytool -list -keystore D:\ Java \ jdk1.5.0_12 \ jre \ lib \ security \ cacerts

    它给出了包含在其中的当前证书的列表密钥库 . 它看起来像这样:

    C:\ Documents and Settings \ NeelanjanaG> keytool -list -keystore D:\ Java \ jdk1.5.0_12 \ jre \ lib \ security \ cacerts输入密钥库密码:changeit密钥库类型:jks密钥库提供者:SUN您的密钥库包含44个条目verisignclass3g2ca,2004年3月26日,trustedCertEntry,证书指纹(MD5):A2:33:9B:4C:74:78:73:D4:6C:E7:C1:F3:8D:CB:5C:E9 entrustclientca,1月9日,2003,trustedCertEntry,证书指纹(MD5):0C:41:2F:13:5B:A0:54:F5:96:66:2D:7E:CD:0E:03:F4 thawtepersonalbasicca,1999年2月13日,trustedCertEntry ,证书指纹(MD5):E6:0B:D2:C9:CA:2D:88:DB:1A:71:0E:4B:78:EB:02:41 addtrustclass1ca,2006年5月1日,trustedCertEntry,证书指纹( MD5):1E:42:95:02:33:92:6B:B9:5F:C0:7F:DA:D6:B2:4B:FC verisignclass2g3ca,2004年3月26日,trustedCertEntry,证书指纹(MD5):F8 :BE:C4:63:22:C9:A8:46:74:8B:B8:1D:1E:4A:2B:F6

    •现在我必须将以前安装的证书包含在cacerts中 .

    •为此,以下是程序:

    keytool -import -noprompt -trustcacerts -alias ALIASNAME -file FILENAME_OF_THE_INSTALLED_CERTIFICATE -keystore PATH_TO_CACERTS_FILE -storepass PASSWORD

    如果您使用的是Java 7:

    keytool -importcert -trustcacerts -alias ALIASNAME -file PATH_TO_FILENAME_OF_THE_INSTALLED_CERTIFICATE -keystore PATH_TO_CACERTS_FILE -storepass changeit

    •然后,它会将证书信息添加到cacert文件中 .

    这是我在上面提到的Exception中找到的解决方案!!

  • 1

    在Linux下使用Tomcat 7,这就行了 .

    String certificatesTrustStorePath = "/etc/alternatives/jre/lib/security/cacerts";
    System.setProperty("javax.net.ssl.trustStore", certificatesTrustStorePath);
    System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
    

    在Linux下, $JAVA_HOME 并不总是设置,但通常 /etc/alternatives/jre 指向 $JAVA_HOME/jre

  • 4

    如何在Tomcat 7中工作

    我想在Tomcat应用程序中支持自签名证书,但是 the following snippet failed to work

    import java.io.DataOutputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    public class HTTPSPlayground {
        public static void main(String[] args) throws Exception {
    
            URL url = new URL("https:// ... .com");
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
    
            httpURLConnection.setRequestMethod("POST");
            httpURLConnection.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
            httpURLConnection.setDoOutput(true);
            DataOutputStream wr = new DataOutputStream(httpURLConnection.getOutputStream());
    
            String serializedMessage = "{}";
            wr.writeBytes(serializedMessage);
            wr.flush();
            wr.close();
    
            int responseCode = httpURLConnection.getResponseCode();
            System.out.println(responseCode);
        }
    }
    

    这就解决了我的问题:

    1)下载.crt文件

    echo -n | openssl s_client -connect <your domain>:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ~/<your domain>.crt
    
    • <your domain> 替换为您的域名(例如 jossef.com

    2)在Java的cacerts证书库中应用.crt文件

    keytool -import -v -trustcacerts -alias <your domain> -file ~/<your domain>.crt -keystore <JAVA HOME>/jre/lib/security/cacerts -keypass changeit -storepass changeit
    
    • <your domain> 替换为您的域名(例如 jossef.com

    • <JAVA HOME> 替换为您的java主目录

    3)哈哈

    即使我在 Java 的默认证书商店中安装了我的证书, Tomcat ignores that (似乎是's not configured to use Java'的默认证书商店) .

    要解决此问题,请在代码中的某处添加以下内容:

    String certificatesTrustStorePath = "<JAVA HOME>/jre/lib/security/cacerts";
    System.setProperty("javax.net.ssl.trustStore", certificatesTrustStorePath);
    
    // ...
    
  • 5

    对于在Ubuntu服务器上运行的Tomcat,要找出正在使用的Java,请使用“ps -ef | grep tomcat”命令:

    样品:

    /home/mcp01$ **ps -ef |grep tomcat**
    tomcat7  28477     1  0 10:59 ?        00:00:18 **/usr/local/java/jdk1.7.0_15/bin/java** -Djava.util.logging.config.file=/var/lib/tomcat7/conf/logging.properties -Djava.awt.headless=true -Xmx512m -XX:+UseConcMarkSweepGC -Djava.net.preferIPv4Stack=true -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.endorsed.dirs=/usr/share/tomcat7/endorsed -classpath /usr/share/tomcat7/bin/bootstrap.jar:/usr/share/tomcat7/bin/tomcat-juli.jar -Dcatalina.base=/var/lib/tomcat7 -Dcatalina.home=/usr/share/tomcat7 -Djava.io.tmpdir=/tmp/tomcat7-tomcat7-tmp org.apache.catalina.startup.Bootstrap start
    1005     28567 28131  0 11:34 pts/1    00:00:00 grep --color=auto tomcat
    

    然后,我们可以进入: cd /usr/local/java/jdk1.7.0_15/jre/lib/security

    默认 cacerts 文件位于此处 . 将不受信任的证书插入其中 .

  • 1

    就我而言,问题是网络服务器只发送证书和中间CA,而不是根CA.添加此JVM选项解决了问题: -Dcom.sun.security.enableAIAcaIssuers=true

    支持Authority Information Access扩展的caIssuers访问方法 . 默认情况下,它是为了兼容性而禁用的,可以通过将系统属性com.sun.security.enableAIAcaIssuers设置为true来启用它 . 如果设置为true,则Sun的CertIXBuilder的PKIX实现使用证书的AIA扩展(除指定的CertStore之外)中的信息来查找颁发的CA证书,前提是它是类型为ldap,http或ftp的URI .

    Source

  • 1

    当我遇到同样的问题时,我正在使用 jdk1.8.0_171 . 我在这里尝试了前2个解决方案(使用keytool添加证书和另一个有黑客入侵的解决方案),但它们对我不起作用 .

    我将JDK升级到 1.8.0_181 ,它就像一个魅力 .

  • 3

    我也有这个问题 .

    我通过向.keystore添加SSL证书来尝试几乎所有内容,但是,它无法使用Java1_6_x . 对我来说,如果我们开始使用较新版本的Java,Java1_8_x作为JVM,它会有所帮助 .

  • 149

    我的cacerts文件完全是空的 . 我通过从我的Windows机器(使用Oracle Java 7)复制cacerts文件并将其scp到我的Linux机箱(OpenJDK)来解决这个问题 .

    cd %JAVA_HOME%/jre/lib/security/
    scp cacerts mylinuxmachin:/tmp
    

    然后在linux机器上

    cp /tmp/cacerts /etc/ssl/certs/java/cacerts
    

    到目前为止,它运作得很好 .

  • 4

    我写了一个小的win32(WinXP 32位testet)愚蠢的cmd(命令行)脚本,它在程序文件中查找所有java版本并为它们添加一个证书 . 密码需要是默认的“changeit”或在脚本中自行更改:-)

    @echo off
    
    for /F  %%d in ('dir /B %ProgramFiles%\java') do (
        %ProgramFiles%\Java\%%d\bin\keytool.exe -import -noprompt -trustcacerts -file some-exported-cert-saved-as.crt -keystore %ProgramFiles%\Java\%%d\lib\security\cacerts -storepass changeit
    )
    
    pause
    

相关问题