【问题标题】:Recipient endpoint doesn't match with SAML response收件人端点与 SAML 响应不匹配
【发布时间】:2014-09-08 11:07:52
【问题描述】:

通常我基于 Spring SAMLService Provider (SP) 实现工作正常,但有时它会返回此错误:

[2014-07-17 16:00:58.767] boot - 1078 DEBUG [http-bio-80-exec-1] --- BaseMessageDecoder:     Successfully decoded message.
[2014-07-17 16:00:58.767] boot - 1078 DEBUG [http-bio-80-exec-1] --- BaseSAMLMessageDecoder: Checking SAML message intended destination endpoint against receiver endpoint
[2014-07-17 16:00:58.768] boot - 1078 DEBUG [http-bio-80-exec-1] --- BaseSAMLMessageDecoder: Intended message destination endpoint: https://prismasp.cloud.reply.eu:443/MIUR_PRISMA-2.1-WEBUI/saml/SSO/alias/defaultAlias
[2014-07-17 16:00:58.768] boot - 1078 DEBUG [http-bio-80-exec-1] --- BaseSAMLMessageDecoder: Actual message receiver endpoint: http://prismasp.cloud.reply.eu:443/MIUR_PRISMA-2.1-WEBUI/saml/SSO/alias/defaultAlias
[2014-07-17 16:00:58.768] boot - 1078 ERROR [http-bio-80-exec-1] --- BaseSAMLMessageDecoder: SAML message intended destination endpoint 'https://prismasp.cloud.reply.eu:443/MIUR_PRISMA-2.1-WEBUI/saml/SSO/alias/defaultAlias' did not match the recipient endpoint 'http://prismasp.cloud.reply.eu:443/MIUR_PRISMA-2.1-WEBUI/saml/SSO/alias/defaultAlias'
[2014-07-17 16:00:58.782] boot - 1078 DEBUG [http-bio-80-exec-1] --- SAMLProcessingFilter: Incoming SAML message is invalid
org.opensaml.xml.security.SecurityException: SAML message intended destination endpoint did not match recipient endpoint
...

我在 Tomcat 7 上使用(作为 Spring Security 的默认设置)HTTP Strict Transport Security (HSTS) >SSL 已启用。

有没有办法修复这个错误?


注意:示例源代码在 Github 上:vdenotaris/spring-boot-security-saml-sample

【问题讨论】:

  • 我认为您错过了 idp 端点中配置的协议中的“s”。您期望“https”,但您似乎收到“http”。
  • 当前配置正常工作,只是有时会导致上述错误。我在想问题是别的。也许我必须手动设置元数据,也许我错过了某个设置(我只是假设)。
  • 该链接给了我一个“Whitelabel 错误页面”。它不是元数据。此外,当您说“通常工作正常”时,这是有线的,它应该总是或永远不会工作!我想这与协议有关。也许有时您从 http 连接,有时从 https 连接。而且您的 idp 似乎期望 https。
  • 只有一个“7”而不是“/”

标签: spring spring-security saml saml-2.0 spring-saml


【解决方案1】:

我在使用 Spring Security SAML 时遇到了同样的问题。所以我不得不从 SAMLContextProviderImpl 更改 contextProvider:

  @Bean
  public SAMLContextProviderImpl contextProvider() {
      return new SAMLContextProviderImpl();
  }

到 SAMLContextProviderLB:

  @Bean
  public SAMLContextProviderLB contextProvider() {
    SAMLContextProviderLB samlContextProviderLB = new SAMLContextProviderLB();
    samlContextProviderLB.setScheme(scheme);
    samlContextProviderLB.setServerName(serverName);
    samlContextProviderLB.setContextPath(contextPath);
      return samlContextProviderLB;
  }

【讨论】:

    【解决方案2】:

    我认为您的应用服务器位于负载平衡器后面!

    对于运行在 AWS 应用程序负载均衡器后面的 Apache Tomcat 服务器,需要启用 RemoteIPValue 以便基于 x-forwarded-proto 标头,Tomcat 将覆盖 scheme (https) 和 port(443) 相应地。

    server.xml

    <Valve className="org.apache.catalina.valves.RemoteIpValve" protocolHeader="X-Forwarded-Proto" internalProxies="10\.\d+\.\d+\.\d+|192\.168\.\d+\.\d+|169\.254\.\d+\.\d+|127\.\d+\.\d+\.\d+|172\.(1[6-9]|2[0-9]|3[0-1])\.\d+\.\d+" />
    

    【讨论】:

      【解决方案3】:

      我不知道您的问题为什么会随机出现,但至少一种解决方法是配置SAMLContextProviderLB 而不是您当前的SAMLContextProviderImpl

      SAMLContextProviderLB 通常用于向 Spring SAML 公开在反向代理或负载均衡器上使用的公共 URL,但在这种情况下,您可以使用它来强制 Spring SAML 认为它正在使用 HTTPS。您可以在Spring SAML manual10.1 高级配置一章中找到详细信息。

      您还应该确保在 MetadataGenerator bean 上正确设置属性 entityBaseURL,因为如果不这样做,生成的元数据将取决于您是使用 http 还是 https 向应用程序发出第一个请求。同样,所有这些都是documented

      【讨论】: