JAVA 6 不支持 SNI,有其他方法可以通过 TLS 验证和接受 SSL 证书吗?

标签 java spring web-services ssl sslhandshakeexception

我知道浏览器和java7不受影响的原因是它们发送服务器名称指示-SNI作为SSL信息的一部分。因此,apache 在开始 SSL 握手并返回正确的证书之前知道要使用哪个虚拟主机。 Java 6 不支持 SNI。所以我的问题是,如何验证并允许证书在 java 6 中被接受。

我做了一个 Spring 客户端来使用 Web 服务,这是我的代码

public class classname1 {

    static {
        System.setProperty("javax.net.ssl.trustStore", "E://Workspace//keystore");
        System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
        System.setProperty("https.protocols", "SSLv3");
        System.setProperty("https.protocols", "TLSv1");

    }
    static {

                HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier()
                    {
                        public boolean verify(String hostname, SSLSession session)
                        {
                            if (hostname.equals("192.168.10.22"))
                                return true;
                            return false;
                        }
                    });
            }

    private static void main(String[] args) {
        try {
            SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
            SOAPConnection soapConnection = soapConnectionFactory.createConnection();

            String url = "https://192.168.10.22/getInformationSearch.asmx?wsdl";
            SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url);
            printSOAPResponse(soapResponse);
            soapConnection.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static SOAPMessage createSOAPRequest() throws Exception {
        // ... Code for request, which will be hitted to url
    }

    private static void printSOAPResponse(SOAPMessage soapResponse) throws Exception {
        // ... Code for response, which will fetch information from webservice
        // URL
    }

}

正如您所看到的代码,我创建了两个方法,1. 用于请求 createSOAPRequest() 2. 用于响应 printSOAPResponse()。 (上面代码片段中的网址名称已更改)

main() 方法中,下面的行将生成请求并将该请求发送到给定的 url SOAPMessagesoapResponse =soapConnection.call(createSOAPRequest(), url); 之后它转到静态 block ,如上面的 HttpsURLConnection.setDefaultHostnameVerifier() 方法所示。

当时,调试器显示:ssl 握手失败并且 SSL 对等点错误关闭。它只发生在 JAVA 6 中,但这些代码可以在 java 7/8 中正常工作。

我在 java 6 中尝试了下面的代码,而不是那个静态 block

 HostnameVerifier hv = new HostnameVerifier() {
                public boolean verify(String urlHostName,
                        SSLSession session) {
                    return true;
                }
            };

但是无论如何都行不通!!!

我正在使用以下 jars xercesImpl.jar、saaj-api.jar、saaj-impl.jar、spring-ws-core-1.5.6.jar、spring-ws-security-1.5.6.jar 和证书这个SSL域名已经导入到keystore中并且它可以在java7/8中运行,所以信任库中没有问题,对吗? (我也使用java 6和7的keytool制作了2个证书,两者在java7/8中都可以正常工作,但在6中则不行)

我关注了这个thread但它不会起作用。那么有没有其他方法可以在 java 6 环境中验证证书并获取响应,或者我应该更改任何 JAR 吗?

最佳答案

如果服务器未配置为允许您在没有 SNI 的情况下进行连接,则不能。

如果没有 SNI,服务器无法确定您想要哪个虚拟主机,直到建立 SSL 连接之后。

要查看差异,如果您有 OpenSSL,可以使用 the s_client option提取所提供的不同证书,或者可能会注意到在不使用 SNI 时连接失败:

SNI:

echo | openssl s_client -servername www.virtualhost.com -connect 192.168.1.55:443 | openssl x509 -text

192.168.1.55 替换为服务器的实际 IP 地址,将 www.virtualhost.com 替换为您要连接的虚拟主机的主机名。管道前面的 echo 命令可防止 openssl 挂起等待输入。

没有 SNI:

echo | openssl s_client -connect 192.168.1.55:443 | openssl x509 -text

如果没有 SNI,您可能会看到完全不同的证书,或者可能会收到连接错误。

关于JAVA 6 不支持 SNI,有其他方法可以通过 TLS 验证和接受 SSL 证书吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39932652/

相关文章:

java - 在 Android 中如何居中每秒变化的文本?

java - TCP网关Spring集成视频教程

spring - 套接字超时异常 : null while opening New Spring Starter Project

java - WAS 7 REST 客户端中的 Jersey 2

java - 如何使用 RESTlet 在 RESTful Web 服务中强制执行 'sessions'?

java - 双倍计算错误

java - Desktop.open() 在某些 JRE 上静默失败

java - 重新上传后 Filenet 文档属性未修改

java - 如何让Tomcat为其提供的WS发布WSDL(CXF 2.2、Spring 3、Tomcat6)

java - Spring jdbctemplate : null pointer exception in set values