在使用Java代码访问我们自己的网站时,会抛出异常:
javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative DNS name matching en.greatfire.org found.
但是,当在浏览器中访问它或使用curl时,没有问题。
知道为什么会这样吗?如果我们的证书存在任何问题,但浏览器在某种程度上更宽松,我们想要解决它。
不确定是否相关,我们为greatfire.org和en.greatfire.org提供单独的证书。
抛出上述异常的Java代码:
URL url = new URL("https://en.greatfire.org");
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
System.out.println("Response code: " + conn.getResponseCode());
for(Entry<String, List<String>> header : conn.getHeaderFields().entrySet()) {
for(String headerValue : header.getValue()) {
System.out.println(header.getKey() + ": " + headerValue);
}
}
答案 0 :(得分:3)
RFC 2818 (the HTTPS specification)说:
如果存在类型为dNSName的subjectAltName扩展名,则必须 用作身份。否则,(最具体的)通用名称 必须使用证书的Subject字段中的字段。虽然 使用Common Name是现有的做法,它已被弃用 鼓励证书颁发机构改为使用dNSName。
基本上,如果根本没有SAN扩展,它应该在Subject DN中使用CN,否则,它应该只使用SAN条目。 (最新的RFC 6125也沿着这些方向发展。)
听起来您的证书中有一个或多个SAN条目,但它们都不适用于您所使用的主机名(仅限CN)。
Java对此非常严格,包括SAN条目的类型(例如IP addresses),但有些浏览器更宽松。我建议通过在主题备用名称中放置要使用的所有主机名(或IP地址)来修复证书。
修改强>
这就是说,你有几个相关的问题。
您为en.greatfire.org
提供的证书包含en.greatfire.org
和www.en.greatfire.org
的SAN条目,这很好,应该可以使用。
但是,如果您使用的客户端不支持SSL / TLS服务器名称指示扩展(例如openssl s_client -showcerts -connect en.greatfire.org:443
或Java 6),则会获得{{1}的证书}和greatfire.org
。
这是一个双重问题,因为:
www.greatfire.org
甚至没有解决同一台机器。看起来您的某个证书很好,但不支持SNI的客户端无法看到它。
如果要避免此问题,请获取对所有4个名称(4个SAN条目)有效的证书,并将greatfire.org
指向正确的IP地址。