我有这样的代码:
// configure the SSLContext with a TrustManager
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(new KeyManager[0],
new TrustManager[] {new DefaultTrustManager()},
new SecureRandom());
SSLContext.setDefault(ctx);
URL url = new URL(urlString); // https://abc.myhost.com
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
System.out.println("verify:" + arg0);
return true;
}
});
System.out.println("HTTP status: " + conn.getResponseCode());
Certificate[] certs = conn.getServerCertificates();
int c=0;
for (Certificate cert : certs){
String t = cert.getType();
System.out.println(String.format("\ncert[%d]: %s",c,t));
c++;
if (pi.verbose) {
System.out.println(cert);
}
else if (cert instanceof X509Certificate) {
X509Certificate x509cert = (X509Certificate) cert;
System.out.println(x509cert.getSubjectDN().getName());
}
}
在 Java 6 上针对特定网站运行此代码,我得到的证书与 Java 7 不同。假设主机名是 abc.myhost.com。
在 Java6 上我得到:
cert[0]: X.509
CN=example.com,OU=Secure Link SSL Pro,O=Company Name Here,
STREET=2001 Space Odyssey Dr,L=Weirton,ST=Wv,2.5.4.17=#13053330303034,C=US
在 Java7 上,我得到:
cert[0]: X.509
CN=abc.myhost.com,OU=Secure Link SSL Pro,O=Company Name Here,
STREET=2001 Space Odyssey Dr,L=Weirton,ST=Wv,2.5.4.17=#13053330303034,C=US
如果我打印出有效日期,那也是不同的。和序列号一样。这些是不同的证书。
在 Java 7 上看起来不错;在 Java 6 上,我在主机名和 CN 之间存在分歧。证书看起来不对。
该服务器完全有可能在代理后面。该服务器的所有者(我正在从事的项目中的合作伙伴)也有可能最近更改了证书。可能有 2 个证书,一个在代理服务器上,一个在代理服务器后面的服务器上。我让他们调查这个。
我的问题是,为什么我不能在 Java7 上得到与在 Java6 上相同的结果?Java 改变了什么HttpsURLConnection.getServerCertificates()
?
对于好奇的人,这只是一种诊断工作。真正的错误是:
javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException:
No subject alternative DNS name matching abc.myhost.com found.
这种情况下的问题通常是证书中的主机名和 CN 不一致。我已经验证了分歧,但仅限于 Java 6。我想了解为什么 Java6 和 Java7 不同。
编辑: Python 2.7.1 脚本返回与 Java6 相同的证书。
SSLConnection.get_peer_cert()
向我显示 CN 不匹配的证书。