Spring Web Services中的主机名验证

时间:2015-09-30 13:42:50

标签: java security ssl soapui spring-ws

我想询问我在Java 1.7上使用Spring Web Services 2.2.2.RELEASE(在Spring Boot 1.3.0.M4下)观察到的主机验证行为差异的根源。

配置WebServiceTemplate以使用HttpComponentsMessageSender时,我最终得到的错误如下:

I/O error: Certificate for <uswebservice.uat.hroffice.com> doesn't match any of the subject alternative names: [*.sbcsystems.com, sbcsystems.com]; nested exception is javax.net.ssl.SSLException: Certificate for <uswebservice.uat.hroffice.com> doesn't match any of the subject alternative names: [*.sbcsystems.com, sbcsystems.com]

当我重新配置WebServiceTemplate以使用 HttpsUrlConnectionMessageSender 时,上述错误消失,并且验证主机名(根据RFC 2818)的调用似乎不会发生在上面的例子中(或者至少我无法追踪它)虽然我可以看到Spring的 HttpUrlConnectionMessageSender 的连接( sun.net.www.protocol.https.DelegateHttpsURLConnection:在 createConnection()方法中为 https:// uswebservice.uat.hroffice.com/IWSUAT/customS ... 分配了相应的主机名验证程序 (javax.net.ssl.HttpsURLConnection中$ DefaultHostnameVerifier)

在成功案例中是否发生了主机名验证(我倾向于认为它仍然存在,但我很感激能够发现如何调用)我正在质疑的是 HttpComponentsMessageSender (错误案例)获取证书失败的证书。我检查了Java安装附带的 cacerts 文件( \ jdk1.7.0_76 \ jre \ lib \ security ) - 它不在那里。安全URL(上方)中出现的证书包含正确的主题Alt名称:

Not Critical
DNS Name: *.uat.hroffice.com
DNS Name: uat.hroffice.com

而在产生错误的情况下,证书似乎具有以下Subject Alt Name字段的值,这使得它无法按照规范尝试取消引用上面的URI:

[8]: ObjectId: 2.5.29.17 Criticality=false
SubjectAlternativeName [
  DNSName: *.sbcsystems.com
  DNSName: sbcsystems.com
]

有问题的神秘证书在SoapUI中也是可见的(这是我能够获得的)然而在该工具中运行测试不会产生错误 - 我假设主机名验证正在某种程度上绕过那里(也许有人知道细节)。

证书是两个不同的证书,因为它们有不同的到期日期。

我还尝试通过提供 HostnameVerifier 的noop实现来禁用主机名验证,但这似乎是一种有问题的安全方法,所以在放弃它的过程中我被所描述的问题弄得一团糟以上。

如果有人能够对我正在经历的症状有所了解,我会提前感激。

以下是相关的Spring配置:

@Bean
public KeyStore keyStore() throws Throwable {
    KeyStoreFactoryBean keyStoreFactory = new KeyStoreFactoryBean();
    keyStoreFactory.setPassword(keyStorePassword);
    keyStoreFactory.setLocation(new ClassPathResource(keyStoreName));
    keyStoreFactory.setType("jks");
    keyStoreFactory.afterPropertiesSet();
    return keyStoreFactory.getObject();
}

@Bean 
public KeyManager[] keyManagers() throws Throwable{
    KeyManagersFactoryBean keyManagerFactory = new KeyManagersFactoryBean();
    keyManagerFactory.setKeyStore(keyStore());
    keyManagerFactory.setPassword(keyStorePassword);
    keyManagerFactory.afterPropertiesSet();
    return keyManagerFactory.getObject();
}

@Bean
public HttpsUrlConnectionMessageSender httpsUrlSender() throws Throwable {
    HttpsUrlConnectionMessageSender sender = new HttpsUrlConnectionMessageSender();
    sender.setSslProtocol("TLS");
    sender.setKeyManagers(keyManagers());

    /*sender.setHostnameVerifier(new HostnameVerifier() {

        @Override
        public boolean verify(String arg0, SSLSession arg1) {
            return true;
        }});*/
    return sender;
}




@Bean
public WebServiceTemplate webServiceTemplate() throws Throwable {
    WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
    webServiceTemplate.setMarshaller(marshaller());
    webServiceTemplate.setUnmarshaller(marshaller());
    webServiceTemplate.setDefaultUri(defaultUri);
    webServiceTemplate.setMessageFactory(messageFactory());
    webServiceTemplate.setMessageSender(/*new HttpComponentsMessageSender()*/httpsUrlSender());
    return webServiceTemplate;
}

在ssllabs.com上分析网站时,据报道只能在支持SNI的浏览器中工作,也许从Java中使用它的事实也会对上述行为产生一些影响(但Java 1.7似乎增加了正确的SNI行为)默认情况下)?

enter image description here

0 个答案:

没有答案