SSL握手警报:自升级到Java 1.7.0以来unrecognized_name错误 [英] SSL handshake alert: unrecognized_name error since upgrade to Java 1.7.0

查看:1230
本文介绍了SSL握手警报:自升级到Java 1.7.0以来unrecognized_name错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我今天从Java 1.6升级到Java 1.7。
从那时起,当我尝试通过SSL建立与我的网络服务器的连接时发生错误:

I upgraded from Java 1.6 to Java 1.7 today. Since then an error occur when I try to establish a connection to my webserver over SSL:

javax.net.ssl.SSLProtocolException: handshake alert:  unrecognized_name
    at sun.security.ssl.ClientHandshaker.handshakeAlert(ClientHandshaker.java:1288)
    at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1904)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1027)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1262)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1289)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1273)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:523)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1296)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
    at java.net.URL.openStream(URL.java:1035)

以下是代码:

SAXBuilder builder = new SAXBuilder();
Document document = null;

try {
    url = new URL(https://some url);
    document = (Document) builder.build(url.openStream());
} catch (NoSuchAlgorithmException ex) {
    Logger.getLogger(DownloadLoadiciousComputer.class.getName()).log(Level.SEVERE, null, ex);  
}

它只是一个测试项目,这就是为什么我允许和使用带有代码的不受信任的证书:

Its only a test project thats why I allow and use untrusted certificates with the code:

TrustManager[] trustAllCerts = new TrustManager[]{
    new X509TrustManager() {

        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public void checkClientTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
        }

        public void checkServerTrusted(
                java.security.cert.X509Certificate[] certs, String authType) {
        }
    }
};

try {

    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
} catch (Exception e) {

    Logger.getLogger(DownloadManager.class.getName()).log(Level.SEVERE, null, e);
} 

我成功连接 https://google.com
哪里是我的错?

I sucessfully tried to connect to https://google.com. where is my fault?

谢谢。

推荐答案

Java 7引入了默认启用的SNI支持。我发现某些配置错误的服务器在SSL握手中发出无法识别的名称警告,大多数客户端都会忽略该警告......除了Java。正如 @Bob Kerns 所述,Oracle工程师拒绝修复此错误/功能。

Java 7 introduced SNI support which is enabled by default. I have found out that certain misconfigured servers send an "Unrecognized Name" warning in the SSL handshake which is ignored by most clients... except for Java. As @Bob Kerns mentioned, the Oracle engineers refuse to "fix" this bug/feature.

作为解决方法,他们建议设置 jsse.enableSNIExtension 属性。要允许您的程序无需重新编译即可运行,请按以下方式运行您的应用程序:

As workaround, they suggest to set the jsse.enableSNIExtension property. To allow your programs to work without re-compiling, run your app as:

java -Djsse.enableSNIExtension=false yourClass

该属性也可以在Java代码中设置,但必须在任何SSL操作之前设置 即可。加载SSL库后,您可以更改属性,但它,security / ssl / ClientHandshaker.java /#91rel =noreferrer> 不会产生任何影响。要在运行时禁用SNI(具有上述限制),请使用:

The property can also be set in the Java code, but it must be set before any SSL actions. Once the SSL library has loaded, you can change the property, but it won't have any effect on the SNI status. To disable SNI on runtime (with the aforementioned limitations), use:

System.setProperty("jsse.enableSNIExtension", "false");

设置此标志的缺点是SNI在应用程序的任何位置都被禁用。为了使用SNI并仍然支持配置错误的服务器:

The disadvantage of setting this flag is that SNI is disabled everywhere in the application. In order to make use of SNI and still support misconfigured servers:


  1. 创建 SSLSocket 使用您要连接的主机名。我们将此命名为 sslsock

  2. 尝试运行 sslsock.startHandshake() 。这将阻塞直到它完成或在出错时抛出异常。每当 startHandshake()中发生错误时,都会收到异常消息。如果它等于握手警报:unrecognized_name ,那么你找到了一个配置错误的服务器。

  3. 当你收到 unrecognized_name 警告(在Java中致命),重试打开 SSLSocket ,但这次没有主机名。这有效地禁用了SNI(毕竟,SNI扩展是关于向ClientHello消息添加主机名)。

  1. Create a SSLSocket with the host name you want to connect to. Let's name this sslsock.
  2. Try to run sslsock.startHandshake(). This will block until it is done or throw an exception on error. Whenever an error occurred in startHandshake(), get the exception message. If it equals to handshake alert: unrecognized_name, then you have found a misconfigured server.
  3. When you have received the unrecognized_name warning (fatal in Java), retry opening a SSLSocket, but this time without a host name. This effectively disables SNI (after all, the SNI extension is about adding a host name to the ClientHello message).

对于Webscarab SSL代理,此提交实现了后备设置。

For the Webscarab SSL proxy, this commit implements the fall-back setup.

这篇关于SSL握手警报:自升级到Java 1.7.0以来unrecognized_name错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆