SAML元数据条目的签名信任建立失败

18
为了从远程源获取元数据,我定义了一个 ExtendedMetadataDelegate bean,如下所示:
@Bean
@Qualifier("replyMeta")
public ExtendedMetadataDelegate replyMetadataProvider() throws MetadataProviderException {
    String metadataURL = "https://ststest.mydomain.it/FederationMetadata/2007-06/FederationMetadata.xml";
    final Timer backgroundTaskTimer = new Timer(true);
    HTTPMetadataProvider provider = new HTTPMetadataProvider(
            backgroundTaskTimer, httpClient(), metadataURL);
    provider.setParserPool(parserPool());
    ExtendedMetadataDelegate emd = new ExtendedMetadataDelegate(
            provider, new ExtendedMetadata());
    return emd;
}
为确保签名信任建立,我在JDK密钥库和应用程序密钥库中添加了相关密钥(第二步可能不足),尽管如此,在运行Web应用程序时仍会出现错误。
[2014-08-18 14:36:47.200] boot - 6000 DEBUG [localhost-startStop-1] --- SignatureValidator: Attempting to validate signature using key from supplied credential
[2014-08-18 14:36:47.200] boot - 6000 DEBUG [localhost-startStop-1] --- SignatureValidator: Creating XMLSignature object
[2014-08-18 14:36:47.206] boot - 6000 DEBUG [localhost-startStop-1] --- SignatureValidator: Validating signature with signature algorithm URI: http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
[2014-08-18 14:36:47.207] boot - 6000 DEBUG [localhost-startStop-1] --- SignatureValidator: Validation credential key algorithm 'RSA', key instance class 'sun.security.rsa.RSAPublicKeyImpl'
[2014-08-18 14:36:47.329] boot - 6000 DEBUG [localhost-startStop-1] --- SignatureValidator: Signature validated with key from supplied credential
[2014-08-18 14:36:47.329] boot - 6000 DEBUG [localhost-startStop-1] --- BaseSignatureTrustEngine: Signature validation using candidate credential was successful
[2014-08-18 14:36:47.330] boot - 6000 DEBUG [localhost-startStop-1] --- BaseSignatureTrustEngine: Successfully verified signature using KeyInfo-derived credential
[2014-08-18 14:36:47.330] boot - 6000 DEBUG [localhost-startStop-1] --- BaseSignatureTrustEngine: Attempting to establish trust of KeyInfo-derived credential
[2014-08-18 14:36:47.330] boot - 6000 DEBUG [localhost-startStop-1] --- BasicX509CredentialNameEvaluator: Supplied trusted names are null or empty, skipping name evaluation
[2014-08-18 14:36:47.331] boot - 6000 DEBUG [localhost-startStop-1] --- MetadataCredentialResolver: Attempting PKIX path validation on untrusted credential: [subjectName='CN=ADFS Signing - ststest-replynet.reply.it']
[2014-08-18 14:36:47.346] boot - 6000 ERROR [localhost-startStop-1] --- MetadataCredentialResolver: PKIX path construction failed for untrusted credential: [subjectName='CN=ADFS Signing - ststest-replynet.reply.it']: unable to find valid certification path to requested target
[2014-08-18 14:36:47.347] boot - 6000 DEBUG [localhost-startStop-1] --- PKIXSignatureTrustEngine: Signature trust could not be established via PKIX validation of signing credential
[2014-08-18 14:36:47.347] boot - 6000 DEBUG [localhost-startStop-1] --- BaseSignatureTrustEngine: Failed to establish trust of KeyInfo-derived credential
[2014-08-18 14:36:47.347] boot - 6000 DEBUG [localhost-startStop-1] --- BaseSignatureTrustEngine: Failed to verify signature and/or establish trust using any KeyInfo-derived credentials
[2014-08-18 14:36:47.347] boot - 6000 DEBUG [localhost-startStop-1] --- PKIXSignatureTrustEngine: PKIX validation of signature failed, unable to resolve valid and trusted signing key
[2014-08-18 14:36:47.347] boot - 6000 ERROR [localhost-startStop-1] --- SignatureValidationFilter: Signature trust establishment failed for metadata entry http://ststest-replynet.reply.it/adfs/services/trust
[2014-08-18 14:36:47.349] boot - 6000 ERROR [localhost-startStop-1] --- AbstractReloadingMetadataProvider: Error filtering metadata from https://ststest-replynet.reply.it/FederationMetadata/2007-06/FederationMetadata.xml
org.opensaml.saml2.metadata.provider.FilterException: Signature trust establishment failed for metadata entry

通过设置,该错误将消失:

emd.setMetadataTrustCheck(false); 

...但我想检查已使用的元数据。

有没有一种方法可以解决这个错误?


更新:

我尝试按照以下方式设置ExtendedMetadata,但错误仍然存在。

em.setAlias("defaultAlias");
em.setSigningKey("*.mydomain.it (Go Daddy Secure Certification Authority)");

看起来这是因为“无法找到请求目标的有效认证路径” - 您是否在您的信任存储中拥有所有必需的证书?更多信息请参见https://dev59.com/pOo6XIcBkEYKwwoYJAvV。 - Konstantin V. Salikhov
我将证书添加到了JDK(jre/lib/security/cacerts)和samlKeystore.jks文件中。 - vdenotaris
1
emd.setMetadataTrustCheck(false); 对我有用,谢谢!...我的信任无效且不受我控制。 - Erich
4个回答

27
你很可能已经导入了HTTPS证书,但没有导入用于创建签名的证书 - 它们是不同的。你应该:
  1. 使用元数据中提取的以下内容创建名为 signature.cer 的文件:
    -----BEGIN CERTIFICATE-----
    MIIC7jCCAdagAwIBAgIQa+pSaOoDP6ZL3qAi564CxzANBgkqhkiG9w0BAQs
    FADAzMTEwLwYDVQQDEyhBREZTIFNpZ25pbmcgLSBzdHN0ZXN0LXJlcGx5bm
    V0LnJlcGx5Lml0MB4XDTE0MDQyMTAwMzUyNVoXDTE1MDQyMTAwMzUyNVowM
    zExMC8GA1UEAxMoQURGUyBTaWduaW5nIC0gc3RzdGVzdC1yZXBseW5ldC5y
    ZXBseS5pdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJyI7Se
    +UGGHOGRcwHF8LrmivtcPJyNKyicPJ8UJ8pIsEmgYBnJIrpS05RkYtdUdk+
    aumDlc3ACt23FxGDLy9hkJJlRbZwklzh4W3RqGC3W5Y+t7KeIuB8d7ZrrLb
    2AoJpVHICRagsLjjHMwz9sJUt+PZdUFFc0pZckHba3TY2Y+MgPYVsyjlEkf
    QrwL0ggh23g9Pe1VQ9HaInXZvwVMGWZ1oL4Uk0cW11URa8x53ZOWMQSsksi
    MUlquItssiuJjRnI9Df+GaDxbQJi51esY2EF1o2JxqGJSA71Apy9EahDho8
    eFkfOS0fYbVNBU5X/Wn7BKsf2Rmg3r6mQM94+gAA8CAwEAATANBgkqhkiG9
    w0BAQsFAAOCAQEAIX5FEt5JWtINzy4C0LtTtta3DMOsLIBH3raRr53+6MKG
    sPP75VAt7fYUutopuk5Y2o++sVPuEuTzcogz5Dj8eglDESkPwR0PrlClVcG
    FLFEx9qOOidYIEa90g462niIOgkNkIpb1JRrmZEFo+yrYYdFSR2iXzC3O1f
    7JAhNwi+d4a8cOTrqynqL6p1z+hiWEub39FlWDPacELw9HSDIYY151hiiPz
    vIRQDBOjDg3Ws8fRwYNjJH4ElwjP2z+1r+sktD/kkh8jj3iWhT37JnQG72D
    7c63ovYICwEZUqS4L3vepO0pv6xewkUbfX4KBQbUPaVVgmVUcSecj85mvMx
    42g==
    -----END CERTIFICATE-----
    
  2. 使用以下命令将证书导入到 samlKeystore.jks 中:
    keytool -importcert -alias adfssigning -keystore samlKeystore.jks -file signature.cer
    

这应该是你所需要的全部内容,只需重新启动Tomcat,你的元数据加载现在应该通过了。

如果你包含以下配置HTTP客户端的bean(在Spring SAML 1.0.0.RELEASE中可用),则不需要将HTTPS证书包含在JDK的cacerts中:

<bean class="org.springframework.security.saml.trust.httpclient.TLSProtocolConfigurer"/>

1
你是如何生成 signature.cer 的? - Purefan
1
@Purefan,您可以从身份提供者共享的元数据中获取证书。您可能可以从某个端点(例如:https://idp.hostname/saml2/idp/metadata.php)获取它,请向您正在使用的IPS管理员询问。只需将其放入空文件夹中的BEGIN / END CERTIFICATE标记之间即可。 - loïc
即使将 signing.cer 添加到我的密钥库中,我仍然收到相同的错误消息。有任何想法吗? - Manoj
有没有在Spring或Java中的示例代码,可以快速匹配编辑过的.cer和.jks文件,并与元数据进行匹配?我正在重启服务器以重新测试所有内容,这需要很长时间,然后再删除一个额外的制表符或换行符,接着又要重新启动服务器。 - rd_

9

我发布这篇文章只是为了以防万一,在您已经尝试了接受的答案但仍然遇到相同错误的情况下,本文可能会有所帮助。

我也曾遇到此问题,我已添加IDP的元数据文件并将其证书导入我的应用密钥库中。但仍然存在签名信任验证问题。我在Intellij中格式化了IDP的元数据.xml文件,结果出现了一些问题。一旦我将其未经格式化的元数据文件导入,一切都正常了。


非常感谢,这节省了我很多时间。我仍然不明白格式化如何搞乱了签名。起初我以为是在签名前后添加的空格导致的,但实际上并不是这个原因。也许XML中其他属性上有其他空格导致了问题。 - dj_frunza
1
“首先,通过将数字哈希与从内容计算的值进行比较,验证签名的有效性。” -> 格式化文件意味着更改其内容,这就是为什么签名验证失败的原因。参考 https://docs.spring.io/spring-security-saml/docs/current/reference/html/security.html - dj_frunza

1

我遇到了相同的问题。以下是我用来解决此问题的步骤:

  1. 从IDP元数据文件中提取
  2. 将证书复制到文本文件中并另存为.crt,例如idp.crt
  3. 在密钥库中导入crt文件 keytool -import -alias adfscert -file idp.crt -keystore samlKeystoreold.jks -storepass keystorepassword
  4. 它会询问您是否信任此crt..选择是
  5. 对于某些情况,它会要求以pkcs12格式使用,添加警告消息并执行相应操作
  6. 尝试运行您的应用程序,应该可以工作:)

0
在我的情况下,我必须将导入证书的别名添加到ExtendedMetadataDelegate emd的metadataTrustedKeys属性中。
如果您使用Vladimír Schäfer上面的示例进行导入,则必须编写以下内容:
keytool -importcert -alias adfssigning -keystore samlKeystore.jks -file signature.cer
emd.setMetadataTrustedKeys(Collections.singleton("adfssigning"));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接