我在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 path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302) at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296) at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509) at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216) at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979) at sun.security.ssl.Handshaker.process_record(Handshaker.java:914) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375) at 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) at SSLPoke.main(SSLPoke.java:26) 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(PKIXValidator.java:387) at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292) at sun.security.validator.Validator.validate(Validator.java:260) at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324) at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229) at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124) at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1491) ... 9 more Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141) at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126) at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280) at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382) ... 15 more
如果我在客户端导入证书,则此错误消失,但我认为我不应该这样做,因为这是一个有效的证书。
测试代码如下:
import java.io.InputStream; import java.io.OutputStream; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; /** Establish a SSL connection to a host and port, writes a byte and * prints the response. See * http://confluence.atlassian.com/display/JIRA/Connecting+to+SSL+services */ public class SSLPoke { public static void main(String[] args) { if (args.length != 2) { System.out.println("Usage: "+SSLPoke.class.getName()+" "); System.exit(1); } try { SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault(); SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket(args[0], Integer.parseInt(args[1])); InputStream in = sslsocket.getInputStream(); OutputStream out = sslsocket.getOutputStream(); // Write a test byte to get a reaction :) out.write(1); while (in.available() > 0) { System.out.print(in.read()); } System.out.println("Successfully connected"); } catch (Exception exception) { exception.printStackTrace(); } } }
为什么会发生这种情况,设置SSL证书的正确方法是什么?
答案 0 :(得分:2)
这里的问题是Java默认情况下带有一组非常有限的根CA证书。它“接受”的CA比典型的浏览器少得多。解决此问题的最简单方法是从Chrome或Firefox等浏览器导出一组CA证书,然后使用keytool
将其导入Java的密钥库。
答案 1 :(得分:0)
它正在发生,因为链中的所有证书都不受Java信任库的信任。
最常见的解决方案是将 top 证书(链中的最后一个,最顶层的签名者)导入JRE的lib/security/cacerts
文件。