有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

SSL证书验证在Java中失败,但在其他任何地方都有效

在用Java代码访问我们自己的网站时,会引发一个异常:

javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative DNS name matching en.greatfire.org found.

但是,在浏览器中访问它或使用curl时,没有问题

知道为什么会这样吗?如果我们的证书有任何问题,但浏览器不知何故更加宽松,我们希望解决它

不确定是否相关,我们有greatfire的单独证书。org和en。大火。组织

引发上述异常的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) 个答案

  1. # 1 楼答案

    RFC 2818 (the HTTPS specification)说:

    If a subjectAltName extension of type dNSName is present, that MUST be used as the identity. Otherwise, the (most specific) Common Name field in the Subject field of the certificate MUST be used. Although the use of the Common Name is existing practice, it is deprecated and Certification Authorities are encouraged to use the dNSName instead.

    本质上,如果根本没有SAN扩展,它应该在主题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),那么您将获得greatfire.orgwww.greatfire.org的证书

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

    • 您已经在浏览器上配置了SNI,Java 6、XP上的任何IE版本或3.0版本下的Android(以及其他一些版本)都不支持SNI
    • greatfire.org甚至无法解析同一台机器

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