我知道浏览器和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 SOAPMessage soapResponse = soapConnection.call(createSOAPRequest(), url);
然后将其转到静态块,如上面的HttpsURLConnection.setDefaultHostnameVerifier()
方法所示。
当时,调试器说:ssl握手失败并且SSL对等体错误地关闭。它仅在JAVA 6中发生,但是这些代码在Java 7/8中正常工作。
我尝试使用Java 6中的以下代码代替该静态块
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域的证书已经导入到密钥库中,并且可以在java7 / 8中使用,所以信任库中没有问题吧?(我也使用Java 6和7的keytool制作了2个证书,它们在java7 / 8中都可以,但在6中不能正常工作)
我遵循了该线程,但无法正常工作。那么,在Java 6环境中是否还有其他方法可以验证证书并获得响应,还是应该更改任何JAR?
如果未将服务器配置为允许您在没有SNI的情况下进行连接,则无法这样做。
如果没有SNI,则直到建立SSL连接之后,服务器才能告诉您所需的虚拟主机。
要了解两者之间的区别,如果您使用的是OpenSSL,则可以使用该s_client
选项提取显示的不同证书,或者可能会注意到不使用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,您可能会看到完全不同的证书,或者可能会收到连接错误。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句