我只是在我的服务器上设置SSL证书 . 我很确定他们的设置正确 . 当在浏览器中转到 https://mydomain.com/myapp
时,页面正确加载,绿色锁定显示在地址栏中 .
从Firefox> POSTER执行POST到此 HTTPS
url我得到了有效的回复 .
如果我从Java客户端执行相同的POST,则会收到以下错误:
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
在我的服务器上,我已将CA_ROOT证书放在JAVA ... / jre / lib / security / cacert密钥库中 .
这是我的Java客户端的发布代码 .
URL url = new URL(Global.SERVER_URL);
HttpsURLConnection connection = null;
connection = (HttpsURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setReadTimeout(45000);
connection.setRequestProperty("Content-Type", "text/json");
connection.connect();
PLease Note: THIS IS NOT A SELF SIGNED CERT. It was issued by a CA
我有一种感觉,Glassfish没有发送完整的证书链 . 我查看了浏览器获得的证书,它是完整的证书链 . 我查看了SSL错误,这只是中间证书,而且是我的域名 .
如何让Glassfish发送完整的Cert链?
检查SSL链
openssl.exe s_client -connect mydomain.com:443
Returns
WARNING: can't open config file: /usr/local/ssl/openssl.cnf
Loading 'screen' into random state - done
CONNECTED(00000190)
depth=0 C = US, ST = <edited>, L = <edited>, O = <edited>, OU = <edited>, CN = <edited>
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 C = US, ST = <edited>, L = <edited>, O = <edited>, OU = <edited>, CN = <edited>
verify error:num=27:certificate not trusted
verify return:1
depth=0 C = US, ST = <edited>, L = <edited>, O = <edited>, OU = <edited>, CN = <edited>
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
0 s:/C=US/ST=<edited>/L=<edited>/O=<edited>/OU=<edited>/CN=<edited>
i:/O=Cybertrust Inc/CN=Cybertrust Public SureServer SV CA
---
Server certificate
-----BEGIN CERTIFICATE-----
<edited>
-----END CERTIFICATE-----
subject=/C=US/ST=<edited>/L=<edited>/O=<edited>/OU=<edited>/CN=<edited>
issuer=/O=Cybertrust Inc/CN=Cybertrust Public SureServer SV CA
---
No client certificate CA names sent
---
SSL handshake has read 1676 bytes and written 513 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES128-GCM-SHA256
Session-ID: <edited>
Session-ID-ctx:
Master-Key: <edited>
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1410274974
Timeout : 300 (sec)
Verify return code: 21 (unable to verify the first certificate)
---
read:errno=0
解决方案
Accepted Answer from Bruno for the Concept
额外细节:
-
获取Keystore Explorer . 它是浏览密钥库的神奇GUI工具 .
-
使用Keystore Explorer打开keystore.jks .
-
右键单击有问题的证书(mydomain)和 View Details>Certificate Chain Details .
-
如果它没有显示完整的Cert链,则通过右键单击cert Edit Certificate Chain>Append Certificate 添加它 .
-
重启Glassfish .
5 回答
证书链
0 s:/ C = US / ST = <编辑> / L = <编辑> / O = <编辑> / OU = <编辑> / CN = <编辑>
i:/ O = Cybertrust Inc / CN = Cybertrust Public SureServer SV CA.
与您在评论中所说的不同,根据此输出,您的服务器不会发送任何中间证书 . 证书链只有一个证书(位置0):服务器证书 .
在服务器端的信任库中添加中间证书对服务器提供的链没有影响(它仅用于验证客户端,如果适用) .
您需要确保您的密钥库条目设置为完整链,如this question中所述,遵循与this answer相同的过程 .
您在浏览器中看到的可能是它重建的链,浏览器也可能知道这些中间CA证书,而JRE可能不会(使用不同的信任锚集):您只会增加默认JRE通过正确显示完整链接受您的服务器证书 . (请注意,您不需要在链中提供根CA证书本身,它不会造成损害,但它只是网络开销 . )
浏览器和Java使用不同的受信任根证书集,默认情况下,浏览器从操作系统获取此信息,Java支持自己的列表,这就是为什么它在浏览器中可能是绿色的并且在Java中不支持
要检查哪些证书支持您的Java版本:
<jre_path>\bin\keytool -keystore "<jre_path>\lib\security\cacerts" -storepass changeit -list
如果您没有看到您的证书,只需将其添加到
<jre_path>\lib\security\cacerts
文件中 .SSLHandshakeException:
通过使用以下代码发送HTTP POST请求的详细示例 .
如果响应代码是200,则意味着好看 .
有关更多详细信息,请参阅以下链接 .
How to solve javax.net.ssl.SSLHandshakeException Error?
Test trusted certificate
Test a Java SSL connection
Java密钥库是 cacerts ,但不是 cacert .
我想你正在讨论我在这里回答的同一个问题:
https://stackoverflow.com/a/25734956/1083338