Java证书验证失败 - 但在其他任何地方都可以使用

时间:2012-03-30 12:10:19

标签: java ssl ssl-certificate

在使用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);
        }
    }

1 个答案:

答案 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.orgwww.en.greatfire.org的SAN条目,这很好,应该可以使用。

但是,如果您使用的客户端不支持SSL / TLS服务器名称指示扩展(例如openssl s_client -showcerts -connect en.greatfire.org:443或Java 6),则会获得{{1}的证书}和greatfire.org

这是一个双重问题,因为:

  • 您已经在浏览器上配置了SNI,Java 6不支持任何版本的IE或Android 3.0版本的IE(可能还有其他几种版本)。
  • www.greatfire.org甚至没有解决同一台机器。

看起来您的某个证书很好,但不支持SNI的客户端无法看到它。 如果要避免此问题,请获取对所有4个名称(4个SAN条目)有效的证书,并将greatfire.org指向正确的IP地址。