XPath для подтверждения

Я пишу PHP-скрипт, который должен получить токен Assertion как часть процесса для входа в SharePoint в Интернете. Я могу получить ответ конверта, который включает в себя токен, который мне нужен.

Как бы я проанализировал часть saml:Assertion этого ответа?

<s:envelope xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">
 <s:header>
 <a:action s:mustunderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue</a:action>
 <o:security xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" s:mustunderstand="1">
 <u:timestamp u:id="_0">
 <u:created>2014-07-01T13:50:22.480Z</u:created>
 <u:expires>2014-07-01T13:55:22.480Z</u:expires>
 </u:timestamp>
 </o:security>
 </s:header>
 <s:body>
 <t:requestsecuritytokenresponse xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
 <t:lifetime>
 <wsu:created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2014-07-01T13:50:22.476Z</wsu:created>
 <wsu:expires xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2014-07-01T14:50:22.476Z</wsu:expires>
 </t:lifetime>
 <wsp:appliesto xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
 <wsa:endpointreference xmlns:wsa="http://www.w3.org/2005/08/addressing">
 <wsa:address>urn:federation:MicrosoftOnline</wsa:address>
 </wsa:endpointreference>
 </wsp:appliesto>
 <t:requestedsecuritytoken>
 <saml:assertion xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" majorversion="1" minorversion="1" assertionid="_56f0eee3-ca21-4885-a40d-4ae543e9bfc8" issuer="http://paychex.com/adfs/services/trust/" issueinstant="2014-07-01T13:50:22.480Z">
 <saml:conditions notbefore="2014-07-01T13:50:22.476Z" notonorafter="2014-07-01T14:50:22.476Z">
 <saml:audiencerestrictioncondition>
 <saml:audience>urn:federation:MicrosoftOnline</saml:audience>
 </saml:audiencerestrictioncondition>
 </saml:conditions>
 <saml:attributestatement>
 <saml:subject>
 <saml:nameidentifier format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">qo3X1/EAe0Ci5pXaS+p8JA==</saml:nameidentifier>
 <saml:subjectconfirmation>
 <saml:confirmationmethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</saml:confirmationmethod>
 </saml:subjectconfirmation>
 </saml:subject>
 <saml:attribute attributename="UPN" attributenamespace="http://schemas.xmlsoap.org/claims">
 <saml:attributevalue>[removed_email]</saml:attributevalue>
 </saml:attribute>
 <saml:attribute attributename="ImmutableID" attributenamespace="http://schemas.microsoft.com/LiveID/Federation/2008/05">
 <saml:attributevalue>qo3X1/p8JA==</saml:attributevalue>
 </saml:attribute>
 </saml:attributestatement>
 <saml:authenticationstatement authenticationmethod="urn:oasis:names:tc:SAML:1.0:am:password" authenticationinstant="2014-07-01T13:50:22.473Z">
 <saml:subject>
 <saml:nameidentifier format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">qo3X1/EAe0p8JA==</saml:nameidentifier>
 <saml:subjectconfirmation>
 <saml:confirmationmethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</saml:confirmationmethod>
 </saml:subjectconfirmation>
 </saml:subject>
 </saml:authenticationstatement>
 <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="#_56f0eee3-ca21-4885-a40d-4ae543e9bfc8">
 <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:transform></ds:transform></ds:transforms>
 <ds:digestmethod algorithm="http://www.w3.org/2000/09/xmldsig#sha1">
 <ds:digestvalue>ZzoryFYQWfks=</ds:digestvalue>
 </ds:digestmethod></ds:reference>
 </ds:signaturemethod></ds:canonicalizationmethod></ds:signedinfo>
 <ds:signaturevalue>**************************************************************************/UY55dMjbiyWt9gyToQPrGBPjG+VX3pEz8XpXV4jrYYXJ/YMpHxdzD/OBzR/bpA+lzebkuP19woqV49ScmJ5TN4b26LEW/ynogYnNl7EEBAJR0wL9CjY6uQCNaERY0X29nyNusQyNTNW4jGeMyBu9KnfVRpVyROd4QxfwV/F8OwGlePRGPypN/VYnLRjfizS674XJ31VmLERwxgn5Xx/0bKDsNw7c5G2qFZmSi7YUxccwMxU6Ypih7D5i73uPrk7oMnRbMHsyxCQ==</ds:signaturevalue>
 <******* xmlns="http://www.w3.org/2000/09/xmldsig#">
 <x509data>
 <x509certificate>MIIC3DCCAcSgAwIBAgIQXIfoKmHCypFBv4Ze44WbzzANBgkqhkiG9w0BAQsFADAqMSgwJgYDVQQDEx9BREZTIFNpZ25pbmcgLSBhZGZzLnBheWNoZXguY29tMB4XDTE0MDQyNDAyMDY1NloXDTE5MDQyMzAyMDY1NlowKjEoMCYGA1UEAxMfQURkhc6NJSB8fJK+Uf/ldkC8VISTp7CW9S3TwXHKn4plqMLSY7NRYII4OPDkLXA9dGx3FQGNQoTe/uH1JGaNZlAGJp4W2Sz9r1i9Ry4lu+L0G3Q==</x509certificate>
 </x509data>
 </*******>
 </ds:signature>
 </saml:assertion>
 </t:requestedsecuritytoken>
 <t:requestedattachedreference>
 <o:securitytokenreference xmlns:k="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" k:tokentype="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1">
 <o:keyidentifier valuetype="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID">_56f0eee3-ca21-4885-a40d-4ae543e9bfc8</o:keyidentifier>
 </o:securitytokenreference>
 </t:requestedattachedreference>
 <t:requestedunattachedreference>
 <o:securitytokenreference xmlns:k="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" k:tokentype="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1">
 <o:keyidentifier valuetype="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID">_56f0eee3-ca21-4885-a40d-4ae543e9bfc8</o:keyidentifier>
 </o:securitytokenreference>
 </t:requestedunattachedreference>
 <t:tokentype>urn:oasis:names:tc:SAML:1.0:assertion</t:tokentype>
 <t:requesttype>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:requesttype>
 <t:keytype>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</t:keytype>
 </t:requestsecuritytokenresponse>
 </s:body>
</s:envelope>

Мой фрагмент кода PHP для анализа этого ответа:

// Parse security token from response
$xml = new DOMDocument();
$xml->loadXML($result);
$xpath = new DOMXPath($xml);
$nodelist = $xpath->query("/*[local-name()='name']:Body/*[local-name()='name']:RequestSecurityTokenResponse/*[local-name()='name']:RequestedSecurityToken/*[local-name()='name']:Assertion");

foreach ($nodelist as $n){
 return $n->nodeValue;
 break;
}

Спасибо за вашу помощь, Тим

2 ответа

Я попытался использовать //saml: Assertion, но это не сработало

Сначала вам нужно зарегистрировать префикс пространства имен - выражения XPath не волнуют, какие префиксы использовались в исходном документе, вам необходимо привязать префиксы к пространствам имен.

$xpath->registerNamespace("s", "urn:oasis:names:tc:SAML:1.0:assertion");
$nodelist = $xpath->query("//s:Assertion");

Но это, вероятно, все равно даст вам значение null, потому что "значение узла" узла элемента в DOM определено в спецификации всегда равным нулю. Если вам нужен текст внутри узла элемента, вам нужно использовать textContent вместо nodeValue, но в этом случае вам, вероятно, придется углубиться в дерево, чтобы найти бит, который вы действительно хотите.


Чтобы просто извлечь значение, в XPath 1.0 вы можете использовать следующее выражение, которое игнорирует пространства имен:

/*[local-name()='Envelope']
 /*[local-name()='Body']
 /*[local-name()='RequestSecurityTokenResponse']
 /*[local-name()='RequestedSecurityToken']
 /*[local-name()='Assertion']

или используя ось потомка:

//*[local-name()='Assertion']

Игнорирование пространств имен должно быть вторым вариантом. Если вы можете зарегистрировать их, как было предложено @IanRoberts, в другом ответе это лучше.

Любое из этих выражений вернет набор узлов, содержащий все найденные элементы Assertion (все дерево). Значение узла или текстовое содержимое этих узлов могут быть не такими, какие вы хотите выбрать. Например, если вы хотите получить X509Certificate вы должны использовать контекстное выражение XPath для этого элемента и извлечь его text(). Такую же стратегию следует использовать, если требуется атрибут дочернего элемента.

Обновление Добавленный PHP-код использует цикл for только для извлечения первого узла. Вы можете использовать для этого item(0). Предполагая, что в каждом документе есть только одно утверждение, ключ, сертификат и т.д., Вы можете использовать выражения XPath для получения именно того, что вы хотите. Например, чтобы получить текст X509Certificate (игнорируя пространства имен и шаги промежуточного местоположения), вы можете использовать:

$key_cert = $xpath->query("//*[local-name()='X509Certificate']")->item(0)->textContent

licensed under cc by-sa 3.0 with attribution.