【问题标题】:Query XML [SAML 2.0 Response]查询 XML [SAML 2.0 响应]
【发布时间】:2014-03-27 15:49:26
【问题描述】:

下面的 xml 给我带来了困难。我需要用 c# 从 XML 中检索以下内容,你能帮忙吗?还有在 C# 中读取/解析 SAML 2.0 响应的更好方法吗?

  • 来自<samlp:StatusCode value="urn:oasis:names:tc:SAML:2.0:status:**Success**"/>的状态码

  • FIRSTNAME 值

  • 姓氏值
  • 邮件值
  • 来自<saml:Issuer>**sso.localhost.dev**</saml:Issuer>的发行者
  • 来自<saml:Audience>**Application-Test**</saml:Audience>的观众

XML

    <samlp:Response Destination="http://localhost/SamlAuthenticate" IssueInstant="2014-03-27T14:49:35.395Z" ID="kBWlU3VWF.Ee6DKbkEpFomtlDAT" Version="2.0" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">sso.localhost.dev</saml:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#kBWlU3VWF.Ee6DKbkEpFomtlDAT"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>LgH7ZZJWwp5fN02IPteWxh9oAQ8=</ds:DigestValue></ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>gBCZ4upHHdYzrVUcTe4Nf+fElY51UFQOJcf81DFPFNKfFxZfLjnX88NwJ6O7CVU3YNo08EINoEpkvEu+f2oxI3VQVnYnT1EYpLGy1+6qpxsFaPbXaQ8h1/NCwAygir1NDu/sktAzRZ2tg2i5rVn2sevY3Y+47SKnB+hG4ukVHusmNumD0NXyKwKNPflG9XEhrLj3bw5xuftr5CAREX5s1VotANFs1HeJA7OE1Yq2yLhw7GmPsa1+fgYQh5tfFRCmvdnpVoiT+SXwoxlRSbWlf2BWgBOLbC8W4dhTpMFmp70lndk0Pwpnxj6z4jFAHT3z/SdGgm0Ow+TbuutceBIIAQ==</ds:SignatureValue>
</ds:Signature>
<samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status>
<saml:Assertion Version="2.0" IssueInstant="2014-03-27T14:49:35.404Z" ID="w4BForMipBizsG1TA7d9QzhCM0-" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<saml:Issuer>sso.localhost.dev</saml:Issuer>
<saml:Subject>
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">JSMITH009</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData NotOnOrAfter="2014-03-27T14:54:35.404Z" Recipient="http://localhost/SamlAuthenticate"/></saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotOnOrAfter="2014-03-27T14:54:35.404Z" NotBefore="2014-03-27T14:44:35.404Z">
<saml:AudienceRestriction>
<saml:Audience>Application-Test</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2014-03-27T14:49:35.404Z" SessionIndex="w4BForMipBizsG1TA7d9QzhCM0-">
<saml:AuthnContext>
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema">
<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="FIRSTNAME">
<saml:AttributeValue xsi:type="xs:string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">john</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="MAIL">
<saml:AttributeValue xsi:type="xs:string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">john.smith@email.localhost.dev</saml:AttributeValue></saml:Attribute>
<saml:Attribute NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" Name="LASTNAME"><saml:AttributeValue xsi:type="xs:string" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">smith</saml:AttributeValue></saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
</samlp:Response>

【问题讨论】:

    标签: c# xml saml-2.0


    【解决方案1】:

    找到解决方案!

    public class SAMLProcessor
    {
    
        #region Properties
        public string DecodedSAML { get; set; }
        public string EncodedeSAML { get; set; }
        public string Audience { get; set; }
        public string SubjectNameID { get; set; }
        public string FirstName { get; set; }
        public string Mail { get; set; }
        public string LastName { get; set; }
        public bool AuthenticationStatus { get; set; }
        public string Issuer { get; set; }
        public string Destination { get; set; }
        public string ResponseID { get; set; }
        public bool VerifiedResponse { get; set; }
        public string SignatureValue { get; set; }
        public string SignatureReferenceDigestValue { get; set; }
        public DateTime AutheticationTime { get; set; }
        public string AuthenticationSession { get; set; }
        #endregion
    
    
        #region Ctror
        public SAMLProcessor(string rawSamlData)
        {
            EncodedeSAML = rawSamlData;
            // the sample data sent us may be already encoded, 
            // which results in double encoding
            if (rawSamlData.Contains('%'))
            {
                rawSamlData = HttpUtility.UrlDecode(rawSamlData);
            }
    
            // read the base64 encoded bytes
            string samlAssertion = Decode64Bit(rawSamlData);
            DecodedSAML = samlAssertion;
            SamlParser(DecodedSAML);
        }
        #endregion
    
        private static string Decode64Bit(string rawSamlData)
        {
            byte[] samlData = Convert.FromBase64String(rawSamlData);
    
            // read back into a UTF string
            string samlAssertion = Encoding.UTF8.GetString(samlData);
            return samlAssertion;
        }
    
        /// <summary>
        /// 
        /// </summary>
        /// <param name="samldata"></param>
        /// <returns></returns>
        public string SamlParser(string samlXMLdata)
        {
    
            //samldata = Decode64Bit("PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4=") + samldata;
            string samldata = samlXMLdata;
    
            if (!samldata.StartsWith(@"<?xml version="))
            {
                samldata = Decode64Bit("PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4=") + samldata;
            }
    
            string firstName = string.Empty;
            XmlDocument xDoc = new XmlDocument();
            samldata = samldata.Replace(@"\", "");
            xDoc.LoadXml(samldata);
            //xDoc.Load(new System.IO.TextReader());//Suppose the xml you have provided is stored in this xml file.
    
            XmlNamespaceManager xMan = new XmlNamespaceManager(xDoc.NameTable);
            xMan.AddNamespace("samlp", "urn:oasis:names:tc:SAML:2.0:protocol");
            xMan.AddNamespace("saml", "urn:oasis:names:tc:SAML:2.0:assertion");
            xMan.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#");
    
    
            XmlNode xNode = xDoc.SelectSingleNode("/samlp:Response/samlp:Status/samlp:StatusCode/@Value", xMan);
            if (xNode != null)
            {
                this.AuthenticationStatus = false;
                string statusCode = xNode.Value;
                if (statusCode.EndsWith("status:Success"))
                {
                    this.AuthenticationStatus = true;
                }
    
            }
    
            xNode = xDoc.SelectSingleNode("/samlp:Response/@Destination", xMan);
            if (xNode != null)
            {
                this.Destination = xNode.Value;
            }
            xNode = xDoc.SelectSingleNode("/samlp:Response/@IssueInstant", xMan);
            if (xNode != null)
            {
                this.AutheticationTime = Convert.ToDateTime(xNode.Value);
            }
            xNode = xDoc.SelectSingleNode("/samlp:Response/@ID", xMan);
            if (xNode != null)
            {
                this.ResponseID = xNode.Value;
            }
            xNode = xDoc.SelectSingleNode("/samlp:Response/saml:Issuer", xMan);
            if (xNode != null)
            {
                this.Issuer = xNode.InnerText;
            }
    
            xNode = xDoc.SelectSingleNode("/samlp:Response/ds:Signature/ds:SignedInfo/ds:Reference/ds:DigestValue", xMan);
            if (xNode != null)
            {
                this.SignatureReferenceDigestValue = xNode.InnerText;
            }
            xNode = xDoc.SelectSingleNode("/samlp:Response/ds:Signature/ds:SignatureValue", xMan);
            if (xNode != null)
            {
                this.SignatureValue = xNode.InnerText;
            }
            xNode = xDoc.SelectSingleNode("/samlp:Response/saml:Assertion/@ID", xMan);
            if (xNode != null)
            {
                this.AuthenticationSession = xNode.Value;
            }
    
            xNode = xDoc.SelectSingleNode("/samlp:Response/saml:Assertion/saml:Subject/saml:NameID", xMan);
            if (xNode != null)
            {
                this.SubjectNameID = xNode.InnerText;
            }
            xNode = xDoc.SelectSingleNode("/samlp:Response/saml:Assertion/saml:Conditions/saml:AudienceRestriction/saml:Audience", xMan);
            if (xNode != null)
            {
                this.Audience = xNode.InnerText;
            }
    
            //reverse order
            //</saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion></samlp:Response>
    
            //string xQryStr = "//NewPatient[Name='" + name + "']";
    
            //XmlNode matchedNode = xDoc.SelectSingleNode(xQryStr);
            // samlp:Response  saml:Assertion saml:AttributeStatement saml:Attribute
            xNode = xDoc.SelectSingleNode("/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute[@Name = 'FIRSTNAME']/saml:AttributeValue", xMan);
            if (xNode != null)
            {
                this.FirstName = xNode.InnerText;
            }
    
            // samlp:Response  saml:Assertion saml:AttributeStatement saml:Attribute
            xNode = xDoc.SelectSingleNode("/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute[@Name = 'MAIL']/saml:AttributeValue", xMan);
            if (xNode != null)
            {
                this.Mail = xNode.InnerText;
            }
    
            // samlp:Response  saml:Assertion saml:AttributeStatement saml:Attribute
            xNode = xDoc.SelectSingleNode("/samlp:Response/saml:Assertion/saml:AttributeStatement/saml:Attribute[@Name = 'LASTNAME']/saml:AttributeValue", xMan);
            if (xNode != null)
            {
                this.LastName = xNode.InnerText;
            }
    
            return this.FirstName;
        }
    }
    

    【讨论】:

      【解决方案2】:

      如果只想解析 XML,可以将其加载到 XElement 中。

      您还可以使用Kentor.AuthServices 包的Saml2Response 类来解析和验证响应。

      【讨论】:

        猜你喜欢
        • 2014-09-28
        • 2021-04-15
        • 1970-01-01
        • 1970-01-01
        • 2017-12-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-25
        相关资源
        最近更新 更多