【问题标题】:Java refusing certificate that browser acceptsJava拒绝浏览器接受的证书
【发布时间】:2016-09-16 23:54:17
【问题描述】:

我在 Wildfly 9 中配置有效证书(不是自签名!)时遇到问题。我已在 Wildfly 中配置了 HTTPS 连接器:

            <https-listener name="https" socket-binding="https" security-realm="UndertowRealm" />

安全领域:

        <security-realm name="UndertowRealm">
          <server-identities>
            <ssl>
              <keystore path="domain.p12" relative-to="jboss.server.config.dir" keystore-password="password"
                alias="appcert"  />
            </ssl>
          </server-identities>
        </security-realm>

并使用以下命令生成密钥库:

openssl pkcs12 -export -in domain.crt -inkey domain.key -out domain.p12 -name appcert -CAfile cafile.crt -caname root

现在,当我在浏览器中打开应用程序时,一切正常。浏览器将证书识别为有效证书,而不会像在自签名证书中那样提示异常。

但是,当我尝试通过 SSLPoke.java 连接到同一个 URL 时,出现以下异常:

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) 在 sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296) 在 sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509) 在 sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216) 在 sun.security.ssl.Handshaker.processLoop(Handshaker.java:979) 在 sun.security.ssl.Handshaker.process_record(Handshaker.java:914) 在 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:26) 原因: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:1491) ... 9 更多 原因: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 更多

如果我在客户端中导入证书,这个错误就会消失,但我认为我不应该这样做,因为这是一个有效的证书。

测试代码如下:

导入 java.io.InputStream; 导入 java.io.OutputStream; 导入 javax.net.ssl.SSLSocket; 导入 javax.net.ssl.SSLSocketFactory; /** 建立到主机和端口的 SSL 连接,写入一个字节和 * 打印响应。看 * http://confluence.atlassian.com/display/JIRA/Connecting+to+SSL+services */ 公共类 SSLPoke { 公共静态无效主要(字符串[]参数){ if (args.length != 2) { System.out.println("用法:"+SSLPoke.class.getName()+" "); System.exit(1); } 尝试 { SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault(); SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket(args[0], Integer.parseInt(args[1])); InputStream in = sslsocket.getInputStream(); 输出流输出 = sslsocket.getOutputStream(); // 写一个测试字节来得到一个反应 :) out.write(1); 而(in.available()> 0){ System.out.print(in.read()); } System.out.println("连接成功"); } 捕捉(异常异常){ 异常.printStackTrace(); } } }

为什么会发生这种情况,设置 SSL 证书的正确方法是什么?

【问题讨论】:

    标签: java ssl https


    【解决方案1】:

    这里的问题是 Java 默认带有一组非常有限的根 CA 证书。它“接受”的 CA 比典型浏览器少得多。解决此问题的最简单方法是从 Chrome 或 Firefox 等浏览器导出一组 CA 证书,然后使用 keytool 将它们导入 Java 的密钥库。

    【讨论】:

    • 对我来说,它使用 Comodo 而不是 GlobalSign 的 SSL 证书
    【解决方案2】:

    发生这种情况是因为链中的任何证书都不受 Java 信任库的信任。

    最通用的解决方案是将 top 证书(链中的最后一个,最高签名者)导入 JRE 的 lib/security/cacerts 文件。

    【讨论】:

      猜你喜欢
      • 2014-06-03
      • 1970-01-01
      • 2016-08-24
      • 2015-09-05
      • 2014-07-07
      • 1970-01-01
      • 2018-12-13
      • 2016-11-10
      • 1970-01-01
      相关资源
      最近更新 更多