我今天从Java 1.6升级到Java 1.7。 从那时起,当我试图通过SSL建立连接到我的web服务器时,出现了一个错误:

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);  
}

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

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。 我的错在哪里?

谢谢。


当前回答

而不是依赖apache中的默认虚拟主机机制,您可以定义最后一个使用任意ServerName和通配符ServerAlias的catchall虚拟主机,例如:

ServerName catchall.mydomain.com
ServerAlias *.mydomain.com

这样你就可以使用SNI, apache不会返回SSL警告。

当然,这只有在您可以使用通配符语法轻松描述所有域的情况下才有效。

其他回答

在从Java 1.6_29升级到1.7时,我也遇到过这个问题。

令人震惊的是,我的客户在Java控制面板中发现了一个可以解决这个问题的设置。

在高级选项卡中,你可以勾选“使用兼容SSL 2.0的ClientHello格式”。

这似乎解决了问题。

我们在Internet Explorer浏览器中使用Java小程序。

希望这能有所帮助。

不幸的是,您不能向jarsigner.exe工具提供系统属性。

我已经提交了缺陷7177232,引用了@eckes的缺陷7127374,并解释了为什么它被错误地关闭。

我的缺陷具体是关于对jarsigner工具的影响,但它可能会导致他们重新打开其他缺陷并正确地解决问题。

更新:实际上,它证明你可以提供系统属性Jarsigner工具,它只是不在帮助消息。使用jarsigner -J-Djsse.enableSNIExtension=false

在spring引导和jvm 1.7和1.8时遇到了这个问题。在AWS上,我们没有选项来更改serververname和ServerAlias来匹配(它们是不同的),所以我们做了以下工作:

在构建。Gradle我们添加了以下内容:

System.setProperty("jsse.enableSNIExtension", "false")
bootRun.systemProperties = System.properties

这让我们绕过了“无法识别的名字”的问题。

而不是依赖apache中的默认虚拟主机机制,您可以定义最后一个使用任意ServerName和通配符ServerAlias的catchall虚拟主机,例如:

ServerName catchall.mydomain.com
ServerAlias *.mydomain.com

这样你就可以使用SNI, apache不会返回SSL警告。

当然,这只有在您可以使用通配符语法轻松描述所有域的情况下才有效。

下面是针对apache httpclient 4.5.11的解决方案。我有问题与cert的主题通配符*.hostname.com。它返回了我同样的异常,但我不能使用属性System.setProperty(“jsse。enableSNIExtension”、“假”);因为它在谷歌位置客户端出错。

我找到了简单的解决方案(只修改socket):

import io.micronaut.context.annotation.Bean;
import io.micronaut.context.annotation.Factory;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;

import javax.inject.Named;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import java.io.IOException;
import java.util.List;

@Factory
public class BeanFactory {

    @Bean
    @Named("without_verify")
    public HttpClient provideHttpClient() {
        SSLConnectionSocketFactory connectionSocketFactory = new SSLConnectionSocketFactory(SSLContexts.createDefault(), NoopHostnameVerifier.INSTANCE) {
            @Override
            protected void prepareSocket(SSLSocket socket) throws IOException {
                SSLParameters parameters = socket.getSSLParameters();
                parameters.setServerNames(List.of());
                socket.setSSLParameters(parameters);
                super.prepareSocket(socket);
            }
        };

        return HttpClients.custom()
                .setSSLSocketFactory(connectionSocketFactory)
                .build();
    }


}