Java尝试遵循服务器提供的证书链来验证证书,直到找到它信任的证书(即
cacerts文件中存在的证书)为止。
我们可以使用OpenSSL命令行工具手动验证链:
simon @ lucifer:〜$ openssl s_client -connect eservices3.bus.att.com:443<snipped>---证书链 0秒:/ C = US / ST =乔治亚州/ L =阿尔法利塔/ O = ATT Services,Inc./OU=ATTIT/CN=eservices3.bus.att.com i:/ C = US / O = VeriSign,Inc./OU=VeriSign信任网络/ OU =使用条款,网址为https://www.verisign.com/rpa(c)10 / CN = VeriSign 3类安全服务器CA -G3---
现在,这是问题所在:颁发者(行开头
i:)“ VeriSign
3类安全服务器CA-G3”是中间证书,而不是根证书。AT&T服务器配置错误,应该同时发送自己的证书(“ eservices3.bus.att.com”)
和 中间证书,以便Java可以一直验证到根的链。
为了说明另一种方式,链条应如下所示:
1)VeriSign 3类公共一级证书颁发机构-G5(根) ^ | 被...签名 |2)VeriSign 3类安全服务器CA-G3(中级) ^ | 被...签名 |3)eservices3.bus.att.com(服务器)
- 根(1)在
cacerts
-好的 - SSL握手期间显示服务器证书(3)-好的
- 但是:Java不了解中间件(2)-因此无法端对端验证链
要解决此问题,您可以:
- 要求AT&T修复服务器,以便它在握手期间发送服务器 和 中间证书,或者
- 将中间证书导入Java的密钥库
第一种解决方案是更可取的,因为它可以帮助所有人(不仅限于您),而且风险较小(您可能不会注意到中间证书是否受到威胁)。
如果要将证书作为临时措施导入,请从VeriSign的支持页面(即“中学SSL中间CA证书”)中获取证书,然后:
simon @ lucifer:〜$ keytool -importcert -alias some_alias_of_your_choosing -文件middle_cert_path.crt -keystore your_cacerts_path输入密钥库密码:*****证书已添加到密钥库
删除证书(一旦AT&T共同行动):
simon @ lucifer:〜$ keytool-删除-alias same_alias_as_before -keystore your_cacerts_path



