【问题标题】:Failed to receive SAML response by HTTP post无法通过 HTTP post 接收 SAML 响应
【发布时间】:2019-08-05 16:15:48
【问题描述】:

在 SSO 实现中,验证用户后,我创建了一个 SAMLResponse 对象并使用 IdentityProvider.SendSAMLResponseByHTTPPost() 方法将其发布到默认登陆 URL。

IdentityProvider.SendSAMLResponseByHTTPPost(Response, strAssertionConsumerServiceURL, samlResponseXml, relayState);

samlResponseXml - 包含 SAML 请求 XML

在 ServiceProvider.ReceiveSAMLResponseByHTTPPost() 方法上,我收到以下 Catch 异常。

未能通过 HTTP post 接收 SAML 响应

身份提供者和服务提供者都在同一个网络域中。

附加了 ComponentSpace.SAML2 的日志

ComponentSpace.SAML2 Verbose: 0 : 9:19:44 PM: Missing form variable SAMLResponse
ComponentSpace.SAML2 Verbose: 0 : 9:19:44 PM: Exception: ComponentSpace.SAML2.SAMLBindingException: The form is missing the variable SAMLResponse
ComponentSpace.SAML2 Verbose: 0 : 9:19:44 PM: Exception: ComponentSpace.SAML2.SAMLBindingException: Failed to receive response over HTTP POST. ---> ComponentSpace.SAML2.SAMLBindingException: The form is missing the variable SAMLResponse
   at ComponentSpace.SAML2.Bindings.HTTPPostBinding.GetFormVariables(HttpRequest httpRequest, String messageFormVariableName, XmlElement& samlMessage, String& relayState)
   at ComponentSpace.SAML2.Bindings.HTTPPostBinding.ReceiveResponse(HttpRequest httpRequest, XmlElement& samlMessage, String& relayState)
   --- End of inner exception stack trace ---

【问题讨论】:

  • 您在表单中缺少 SAML,请查看错误。表单缺少变量 SAMLResponse。表单应包含一个名为 SAMLRepsponse 的隐藏字段并作为帖子发布
  • 如果您使用浏览器开发工具或 Fiddler 来捕获 HTTP 流量,您应该能够看到导致此错误的原因。最可能的原因是正在接收 HTTP Get。 SAML 响应应在带有 SAMLResponse 发布数据的 HTTP 发布中发送。
  • 在我的断言页面中,在通过以下方法使用 SAMLResponse 时,ServiceProvider.ReceiveSAMLResponseByHTTPPost(Request, out samlResponseXml, out relayState); 我收到错误“无法通过 HTTP post 接收 SAML 响应”@ComponentSpace 但是,根据代码,它是 POST动词,但 System.Web.HttpRequest 的 Request 对象 上的 Shift+F9 被标识为 GET。而且,这不能改变。如果是这样,仍然如何尝试 POST 呢?
  • 您需要确定收到 HTTP Get 的原因。最好的方法是捕获网络流量。身份提供者应该在 HTTP Post 中发送 SAML 响应。没有在 HTTP Get 中接收 SAML 响应的选项。 HTTP Get 可能源自您的应用程序或某个中间节点,而不是身份提供者。跟踪 HTTP 流量将有助于识别来源。
  • @ComponentSpace - 将 AssertionConsumer URL 指定为 strAssertionConsumerServiceURL = "localhost:58986/AssertionInternal"; POST Http VERB 被调用。能够接收 SAML 响应。谢谢..!!

标签: c# single-sign-on saml


【解决方案1】:

问题
(1) HTTP post接收SAML响应失败

(2)

ComponentSpace.SAML2 Verbose: 0 : 9:19:44 PM: Missing form variable SAMLResponse
ComponentSpace.SAML2 Verbose: 0 : 9:19:44 PM: Exception: ComponentSpace.SAML2.SAMLBindingException: The form is missing the variable SAMLResponse

分辨率

SAML 异常日志指出 SAML Response 的形式/格式不正确。

Creating SAML Response for SSO 提供以下示例代码来演示如何使用 ComponentSpace 库生成 SAML 响应。

        // Create a SAML response with the user's local identity.
        private SAMLResponse CreateSAMLResponse()
        {
            //Trace.Write("IdPreating SAML response");
           SAMLResponse samlResponse = new SAMLResponse();
            samlResponse.Destination = strAssertionConsumerServiceURL;
            Issuer issuer = new Issuer(CreateAbsoluteURL("~/"));
            samlResponse.Issuer = issuer;
            samlResponse.Status = new Status(SAMLIdentifiers.PrimaryStatusCodes.Success, null);
            SAMLAssertion samlAssertion = new SAMLAssertion();
            samlAssertion.Issuer = issuer;
            //Subject subject = new Subject(new NameID(User.Identity.Name));
            Subject subject = new Subject(new NameID());
            SubjectConfirmation subjectConfirmation = new SubjectConfirmation(SAMLIdentifiers.SubjectConfirmationMethods.Bearer);
            SubjectConfirmationData subjectConfirmationData = new SubjectConfirmationData();
            subjectConfirmationData.Recipient = strAssertionConsumerServiceURL;
            subjectConfirmation.SubjectConfirmationData = subjectConfirmationData;
            subject.SubjectConfirmations.Add(subjectConfirmation);
            samlAssertion.Subject = subject;
            samlAssertion.SetAttributeValue("MemberId", this.txtMemberId.Text);
            samlAssertion.SetAttributeValue("Name", this.txtName.Text);
            samlAssertion.SetAttributeValue("Phone", this.txtPhone.Text);
            AuthnStatement authnStatement = new AuthnStatement();
            authnStatement.AuthnContext = new AuthnContext();
            authnStatement.AuthnContext.AuthnContextClassRef = new AuthnContextClassRef(SAMLIdentifiers.AuthnContextClasses.Password);
            samlAssertion.Statements.Add(authnStatement);
           samlResponse.Assertions.Add(samlAssertion);
            return samlResponse;
        }
        // Send the SAML response to the SP.
        private void SendSAMLResponse(SAMLResponse samlResponse, string relayState)
        {
            // Serialize the SAML response for transmission.
            XmlElement samlResponseXml = samlResponse.ToXml();
            // Sign the SAML response.
           X509Certificate2 x509Certificate = (X509Certificate2)Application["IdPX509Certificate"];
            SAMLMessageSignature.Generate(samlResponseXml, x509Certificate.PrivateKey, x509Certificate);
          IdentityProvider.SendSAMLResponseByHTTPPost(Response, strAssertionConsumerServiceURL, samlResponseXml, relayState);
        }

【讨论】:

    【解决方案2】:

    在多次尝试使用 Firebug 控制台和 Fiddler2 后,已确定当我尝试将数据发布到 AssertionConsumerServiceURL 页面时调用了 Http GET,尽管使用了 SendSAMLResponseByHTTPPost() 和 ReceiveSAMLResponseByHTTPPost()。

     string strAssertionConsumerServiceURL = "http://localhost:58986/AssertionInternal.aspx";
    

    上面的 AssertionConsumer 服务 url 被修改为如下,

     string strAssertionConsumerServiceURL = "http://localhost:58986/AssertionInternal";
    

    使用此 URL,SAML POST 数据已成功接收。

    在我的应用程序中指定带有 .aspx 扩展名的 URL 调用了 GET Verb 而不是 POST 动词。

    【讨论】:

    • 感谢您的更新。是的,您指定的断言消费者服务 URL 必须是您调用我们的 API 以接收 SAML 响应的端点的正确 URL。 Web 表单示例使用 .aspx URL。 MVC 示例使用没有此扩展名的 URL。
    • 我遇到了同样的问题,从 URL 中删除 .aspx 扩展名修复了它。有趣的是,当我指向另一个具有相同设置的断言消费者服务时,它可以在不删除 .aspx 扩展名的情况下工作。这两种服务都存在于 Asp.Net 网络表单 WEBSITE 项目中。不是 MVC 也不是 Web 应用程序。也许是一个错误?
    猜你喜欢
    • 1970-01-01
    • 2016-10-25
    • 2021-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多