简体   繁体   English

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

[英]JAVA 6 does not support SNI, Any Alternative way to verify and accept SSL Certificate over TLS?

I know the reason why browsers and java7 are not affected is because they send Server Name Indication-SNI as part of the SSL information. 我知道浏览器和java7不受影响的原因是因为它们将服务器名称指示SNI作为SSL信息的一部分发送。 So, apache knows what virtual host to use before starting SSL handshake and returns the proper certificate. 因此,apache在开始SSL握手之前就知道要使用哪个虚拟主机,并返回正确的证书。 Java 6 doesn't support SNI. Java 6不支持SNI。 So My question is, how do I verify and allow certificate to be accepted in java 6. 所以我的问题是,如何验证并允许Java 6中接受证书。

I made a spring client to consume webservice, Here is my code 我做了一个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
    }

}

As you can see code, I made two methods, 1. for Request createSOAPRequest() 2. for Response printSOAPResponse() . 如您所见,我制作了两种方法:1.用于请求createSOAPRequest() 2.用于响应printSOAPResponse() (Url name is changed in above snippet) (在上面的代码段中更改了网址名称)

In main() method, below line will generate request and send that request to given url SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url); main()方法中,以下行将生成请求并将该请求发送到给定的url SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url); after that it goes to static block as shown above HttpsURLConnection.setDefaultHostnameVerifier() method. 之后,它转到静态块,如HttpsURLConnection.setDefaultHostnameVerifier()方法所示。

At that time,debugger says: ssl handshake failed and SSL peer shut down incorrectly. 当时,调试器说:ssl握手失败并且SSL对等体错误地关闭。 It happens only in JAVA 6 but these code working proper with java 7/8. 它仅在JAVA 6中发生,但是这些代码在Java 7/8中正常工作。

Instead of that static block, I have tried below code in java 6 我尝试使用Java 6中的以下代码代替该静态块

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

But it won't work anyhow!!! 但是无论如何它都行不通!!!

I am using following jars xercesImpl.jar,saaj-api.jar,saaj-impl.jar,spring-ws-core-1.5.6.jar,spring-ws-security-1.5.6.jar and Certificate for this SSL domain has been imported into keystore and It works in java7/8, So there is no issue in truststore right? 我正在使用以下jars xercesImpl.jar,saaj-api.jar,saaj-impl.jar,spring-ws-core-1.5.6.jar,spring-ws-security-1.5.6.jar和此SSL域的证书已经导入到密钥库中,并且可以在java7 / 8中使用,所以信任库中没有问题吧? (I made 2 certificate using keytool of java 6 and 7 as well, both works fine in java7/8 but not in 6) (我也使用Java 6和7的keytool制作了2个证书,在java7 / 8中都可以正常工作,但在6中却不能)

I followed this thread but it wont work. 我遵循了该线程,但无法正常工作。 So is there any alternative way to verify certificate and get response in java 6 environment, or should I change any JAR ? 那么,是否有其他方法可以在Java 6环境中验证证书并获得响应,还是应该更改任何JAR?

As you already mentioned Java 6 does not support SNI. 如前所述,Java 6不支持SNI。 But, the problem of missing SNI is not only with verifying the certificate (because the server sends the wrong certificate) but also that depending on the servers configuration the server will cause a handshake error if the SNI extension is not present and does not point to a hostname available at the server. 但是,缺少SNI的问题不仅在于验证证书(因为服务器发送了错误的证书),而且还取决于服务器的配置,如果不存在SNI扩展并且未指向SNI,则服务器将导致握手错误。服务器上可用的主机名。 And this is obviously the case here: 这显然是这种情况:

... ssl handshake failed and SSL peer shut down incorrectly. ... ssl握手失败,并且SSL对等体错误关闭。 It happens only in JAVA 6 but these code working proper with java 7/8. 它仅在JAVA 6中发生,但是这些代码在Java 7/8中正常工作。

Trying to change the validation of the certificate as you've tried will not help at all in this case because the error occurs before the client even has a certificate to verify. 在这种情况下,尝试更改证书的有效性根本没有帮助,因为该错误发生在客户端甚至没有证书需要验证之前。 This means that there is no way around it: you need to support SNI in your client if you want to communicate with this specific server. 这意味着无法解决它:如果要与此特定服务器通信,则需要在客户端中支持SNI。

You can't if the server isn't configured to allow you to connect without SNI. 如果未将服务器配置为允许您在没有SNI的情况下进行连接,则无法这样做。

Without SNI, the server cannot tell which virtual host you want until after the SSL connection has been established. 如果没有SNI,则直到建立SSL连接 ,服务器才能告诉您想要哪个虚拟主机。

To see the difference, if you have OpenSSL, you can use the s_client option to extract the different certificates presented, or perhaps note a failure to connect when you don't use SNI: 要了解两者之间的区别,如果您使用的是OpenSSL,则可以使用s_client选项提取显示的不同证书,或者可能会注意到不使用SNI时连接失败:

SNI: SNI:

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

Replace 192.168.1.55 with the actual IP address of the server, and www.virtualhost.com with the host name of the virtual host you want to connect to. 192.168.1.55替换为服务器的实际IP地址,并将www.virtualhost.com替换为您要连接的虚拟主机的主机名。 The echo command prepended to the pipeline prevents openssl from hanging in a wait for input. 管道前的echo命令可防止openssl挂起以等待输入。

Without SNI: 没有SNI:

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

Without SNI, you may see a completely different certificate, or you may get a connection error. 如果没有SNI,您可能会看到完全不同的证书,或者可能会收到连接错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM