【问题标题】:correct SAML TLSProtocolSocketFactory configuration正确的 SAML TLSProtocolSocketFactory 配置
【发布时间】:2016-04-18 09:36:33
【问题描述】:

我使用Spring SAML 对用户进行身份验证。
默认情况下,SAML 实现每小时刷新其元数据。
通过org.opensaml.saml2.metadata.provider.AbstractReloadingMetadataProvider.refresh() 的初始运行有效,但所有后续调用(由计时器调用)均失败:

INFO: org.apache.commons.httpclient.HttpMethodDirector - Retrying request
ERROR: org.springframework.security.saml.trust.MetadataCredentialResolver - PKIX path construction failed for untrusted credential: [subjectName='CONTENT_REMOVED_FOR_STACKOVERFLOW']: unable to find valid certification path to requested target
ERROR: org.opensaml.saml2.metadata.provider.HTTPMetadataProvider - Error retrieving metadata from https://HOSTNAME/PATH?cmd=metadata
javax.net.ssl.SSLPeerUnverifiedException: SSL peer failed hostname validation for name: null
    at org.opensaml.ws.soap.client.http.TLSProtocolSocketFactory.verifyHostname(TLSProtocolSocketFactory.java:233)
    at org.opensaml.ws.soap.client.http.TLSProtocolSocketFactory.createSocket(TLSProtocolSocketFactory.java:194)
    at org.springframework.security.saml.trust.httpclient.TLSProtocolSocketFactory.createSocket(TLSProtocolSocketFactory.java:97)
    at org.apache.commons.httpclient.HttpConnection.open(HttpConnection.java:707)
    at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:387)
    at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
    at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
    at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)
    at org.opensaml.saml2.metadata.provider.HTTPMetadataProvider.fetchMetadata(HTTPMetadataProvider.java:250)
    at org.opensaml.saml2.metadata.provider.AbstractReloadingMetadataProvider.refresh(AbstractReloadingMetadataProvider.java:260)
    at org.opensaml.saml2.metadata.provider.AbstractReloadingMetadataProvider$RefreshMetadataTask.run(AbstractReloadingMetadataProvider.java:521)
    at java.util.TimerThread.mainLoop(Timer.java:555)
    at java.util.TimerThread.run(Timer.java:505)
DEBUG: org.opensaml.saml2.metadata.provider.AbstractReloadingMetadataProvider - Error occurred while attempting to refresh metadata from 'https://HOSTNAME/PATH?cmd=metadata'
org.opensaml.saml2.metadata.provider.MetadataProviderException: Error retrieving metadata from https://HOSTNAME/PATH?cmd=metadata
    at org.opensaml.saml2.metadata.provider.HTTPMetadataProvider.fetchMetadata(HTTPMetadataProvider.java:274)
    at org.opensaml.saml2.metadata.provider.AbstractReloadingMetadataProvider.refresh(AbstractReloadingMetadataProvider.java:260)
    at org.opensaml.saml2.metadata.provider.AbstractReloadingMetadataProvider$RefreshMetadataTask.run(AbstractReloadingMetadataProvider.java:521)
    at java.util.TimerThread.mainLoop(Timer.java:555)
    at java.util.TimerThread.run(Timer.java:505)
Caused by: javax.net.ssl.SSLPeerUnverifiedException: SSL peer failed hostname validation for name: null
    at org.opensaml.ws.soap.client.http.TLSProtocolSocketFactory.verifyHostname(TLSProtocolSocketFactory.java:233)
    at org.opensaml.ws.soap.client.http.TLSProtocolSocketFactory.createSocket(TLSProtocolSocketFactory.java:194)
    at org.springframework.security.saml.trust.httpclient.TLSProtocolSocketFactory.createSocket(TLSProtocolSocketFactory.java:97)
    at org.apache.commons.httpclient.HttpConnection.open(HttpConnection.java:707)
    at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:387)
    at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
    at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
    at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)
    at org.opensaml.saml2.metadata.provider.HTTPMetadataProvider.fetchMetadata(HTTPMetadataProvider.java:250)
    ... 4 common frames omitted

我将其追溯到org.springframework.security.saml.trust.httpclient.TLSProtocolConfigurer bean。

<bean class="org.springframework.security.saml.trust.httpclient.TLSProtocolConfigurer">
    <property name="sslHostnameVerification" value="default"/>
    <property name="keyManager" ref="keyManager"/>
</bean>

afterPropertiesSet() 中,这个 bean 覆盖了之前注册的 (org.opensaml.ws.soap.client.http.TLSProtocolSocketFactory) https 协议 (org.apache.commons.httpclient.protocol.Protocol) org.springframework.security.saml.trust.httpclient.TLSProtocolSocketFactory

所以第一次调用使用org.opensaml.ws.soap.client.http.TLSProtocolSocketFactory 有效,所有计时器调用使用org.springframework.security.saml.trust.httpclient.TLSProtocolSocketFactory 失败。

如果我从我的 spring 配置中删除 TLSProtocolConfigurer,一切正常。问题是,我可以在不破坏任何东西的情况下做到这一点吗?
这是我应该报告的错误吗?

【问题讨论】:

    标签: java spring spring-security saml


    【解决方案1】:

    异常表示,它无法验证证书中定义的主机名。因此,您的 Timer 在名称与证书中的名称不匹配的主机上执行。所以这不是错误。

    【讨论】:

    • 好的,但是为什么org.opensaml.ws.soap.client.http.TLSProtocolSocketFactory 不抛出异常呢?有了它,整个refresh() 工作,org.springframework.security.saml.trust.httpclient.TLSProtocolSocketFactory 它失败了。
    • 您的“第一次调用”和调度程序的调用是否来自同一个主机(-name)?如果是这样,那么 Spring TLSProtocolSocketFactory 似乎默认启用了主机名验证,而 OpenSAML TLSProtocolSocketFactory 没有。应该有一个属性或类似的设置这个....
    • 是的,首先和调度程序调用来自同一个主机。在 OpenSAML TLSProtocolSocketFactory 中,hostnameVerifier 设置为 XMLTOOLING_STRICT。在verifyHostname() 方法中,主机被无一例外地验证。
    • 这听起来很奇怪。您的证书中定义了什么主机名,调用的源主机名是什么,即这两个是否相同?
    • 出于安全原因,我不想发布主机名,我不确定证书中是否声明了主机名。但我认为这并不重要,因为在String hostname = sslSession.getPeerHost(); 异常的情况下hostnamenull。这不是第一次通话中的null
    猜你喜欢
    • 2016-07-08
    • 1970-01-01
    • 1970-01-01
    • 2015-12-10
    • 1970-01-01
    • 2016-04-27
    • 1970-01-01
    • 2015-03-24
    • 2013-10-18
    相关资源
    最近更新 更多