【问题标题】:Load metadata from https with Spring SAML使用 Spring SAML 从 https 加载元数据
【发布时间】:2014-09-23 10:39:56
【问题描述】:

我想使用 https 协议从网络导入一些元数据:

@Bean
public HTTPMetadataProvider ssoCircleMetadataProvider()
        throws MetadataProviderException {
    String metadataURL = "https://idp.ssocircle.com/idp-meta.xml";
    final Timer backgroundTaskTimer = new Timer(true);
    HTTPMetadataProvider provider = new HTTPMetadataProvider(
            backgroundTaskTimer, httpClient(), metadataURL);
    provider.setParserPool(parserPool());
    return provider;
}

通过阅读documentation,我发现了这一步:

默认情况下,使用基于 HTTP 的提供程序加载元数据 HTTPS 执行在您的 JDK 中配置的信任验证。如果 你想在你的 keyStore 中使用证书,添加以下内容 更改 HTTP 客户端使用的 socketFactory 的 bean:

<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetClass" value="org.apache.commons.httpclient.protocol.Protocol"/>
    <property name="targetMethod" value="registerProtocol"/>
    <property name="arguments">
        <list>
            <value>https</value>
            <bean class="org.apache.commons.httpclient.protocol.Protocol">
                <constructor-arg value="https"/>
                <constructor-arg>
                    <bean class="org.springframework.security.saml.trust.httpclient.TLSProtocolSocketFactory"/>
                </constructor-arg>
                <constructor-arg value="443"/>
            </bean>
        </list>
    </property>
</bean>

在Java Config中转换,变成:

@Bean
public Protocol httpClientProtocol() {
    org.springframework.security.saml.trust.httpclient.TLSProtocolSocketFactory factory =
            new org.springframework.security.saml.trust.httpclient.TLSProtocolSocketFactory();
    Protocol httpClientProtocol = new Protocol ("https", factory, 443);
    return httpClientProtocol;
}

@Bean
public MethodInvokingFactoryBean methodInvokingFactoryBean() {
    MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
    methodInvokingFactoryBean.setTargetClass(Protocol.class);
    methodInvokingFactoryBean.setTargetMethod("registerProtocol");
    Object[] args = {"https", httpClientProtocol()};
    methodInvokingFactoryBean.setArguments(args);
    return methodInvokingFactoryBean;
}

但未找到 org.springframework.security.saml.trust.httpclient.TLSProtocolSocketFactory 类结果。我正在使用 Spring SAML1.0.0-RC2 版本。

我做错了吗?

如何修复此错误并根据需要加载元数据?


更新

通过使用 SNAPSHOT 存储库,我可以使用 TLSProtocolSocketFactory 类。 我已将 SSOCircle 的证书导入到我的密钥库中,但尽管如此,应用程序仍返回如下错误:

[2014-07-31 17:33:27.596] boot - 11800 ERROR [localhost-startStop-1] --- HTTPMetadataProvider:    Error retrieving metadata from https://idp.ssocircle.com/idp-meta.xml
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

更新 2

我已根据您的建议修复了我的代码。我已将所有证书导入密钥库,但在启动时应用程序返回此错误:

[2014-08-01 10:02:38.961] boot - 14704 DEBUG [localhost-startStop-1] --- BasicX509CredentialNameEvaluator: Supplied trusted names are null or empty, skipping name evaluation
[2014-08-01 10:02:38.962] boot - 14704 DEBUG [localhost-startStop-1] --- MetadataCredentialResolver: Attempting PKIX path validation on untrusted credential: [subjectName='CN=ADFS Signing - ststest-vdenotarisnet.vdenotaris.it']
[2014-08-01 10:02:39.028] boot - 14704 ERROR [localhost-startStop-1] --- MetadataCredentialResolver: PKIX path construction failed for untrusted credential: [subjectName='CN=ADFS Signing - ststest-vdenotarisnet.vdenotaris.it']: unable to find valid certification path to requested target
[2014-08-01 10:02:39.028] boot - 14704 DEBUG [localhost-startStop-1] --- PKIXSignatureTrustEngine: Signature trust could not be established via PKIX validation of signing credential
[2014-08-01 10:02:39.028] boot - 14704 DEBUG [localhost-startStop-1] --- BaseSignatureTrustEngine: Failed to establish trust of KeyInfo-derived credential
[2014-08-01 10:02:39.028] boot - 14704 DEBUG [localhost-startStop-1] --- BaseSignatureTrustEngine: Failed to verify signature and/or establish trust using any KeyInfo-derived credentials
[2014-08-01 10:02:39.029] boot - 14704 DEBUG [localhost-startStop-1] --- PKIXSignatureTrustEngine: PKIX validation of signature failed, unable to resolve valid and trusted signing key
[2014-08-01 10:02:39.029] boot - 14704 ERROR [localhost-startStop-1] --- SignatureValidationFilter: Signature trust establishment failed for metadata entry http://ststest.vdenotaris.local/adfs/services/trust
[2014-08-01 10:02:39.031] boot - 14704 ERROR [localhost-startStop-1] --- AbstractReloadingMetadataProvider: Error filtering metadata from https://ststest.vdenotaris.local/FederationMetadata/2007-06/FederationMetadata.xml
org.opensaml.saml2.metadata.provider.FilterException: Signature trust establishment failed for metadata entry

请注意,使用的证书是由 GoDaddy 验证的。

【问题讨论】:

  • 使用 -Djavax.net.debug=all 启动您的应用程序,让我们看看它的含义 - 日志跟踪应包含有关 PKIX 失败原因的更多详细信息。你的证书有没有可能过期?请仔细检查您是否已将正确的密钥导入 samlKeystore.jks
  • 顺便说一句,我已经简化了配置,一旦你更新到更高版本,你唯一需要做的就是包含类 org.springframework.security.saml.trust.httpclient.TLSProtocolConfigurer 的 bean
  • 导入是正确的,我很确定。证书仍然有效。我会尽快按照建议提供 javax.net 调试选项来检查应用程序。
  • 我确定现在导入是正确的,这不是我的意思 - 我制作了 TLSProtocolConfigurer 来为将来尝试配置相同的人简化它,并想要警告您更新后必须重新配置。
  • 它将在明天的夜间构建中。

标签: java spring spring-security saml spring-saml


【解决方案1】:

TLSProtocolSocketFactory 类仅在主干中可用,并将成为 1.0.0.FINAL 的一部分。 RC2 中唯一的选择是将密钥添加到 JDK 的密钥库中。

更新:

此存储库中提供了 Spring SAML 的快照版本:

<repository>
  <releases>
    <enabled>false</enabled>
  </releases>
  <snapshots>
    <enabled>true</enabled>
  </snapshots>
  <id>com.springsource.repository.maven.snapshot</id>
  <name>SpringSource Enterprise Bundle Maven Repository - SpringSource Snapshot Releases</name>
  <url>http://maven.springframework.org/snapshot</url>
</repository>

您可能想阅读“新增功能”一章,其中列出了自 RC2 以来的更改,其中一些涉及向后兼容性。

另一个更新:

你的初始化错误,TLSFactory需要作为bean启动,你可能还需要MetadataManager中的依赖。

@Bean
public ProtocolSocketFactory socketFactory() {
    return new TLSProtocolSocketFactory();
}

@Bean
public Protocol socketFactoryProtocol() {
    return new Protocol("https", socketFactory(), 443);
}

@Bean
public MethodInvokingFactoryBean socketFactoryInitialization() {
    MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
    methodInvokingFactoryBean.setTargetClass(Protocol.class);
    methodInvokingFactoryBean.setTargetMethod("registerProtocol");
    Object[] args = {"https", socketFactoryProtocol()};
    methodInvokingFactoryBean.setArguments(args);
    return methodInvokingFactoryBean;
}

@Bean
@Qualifier("metadata")
@DependsOn("socketFactoryInitialization")
public CachingMetadataManager metadata() throws MetadataProviderException, IOException     {
  ...
}

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2016-11-25
  • 2016-08-06
  • 2015-07-24
  • 2015-06-08
  • 2015-07-31
  • 2014-10-02
  • 2016-01-26
  • 2020-10-15
相关资源
最近更新 更多