我正在使用.NET core实现saml应用。我有关于
的问题SelectSingleNode(string xpath, XmlNamespaceManager nsmgr)
我的SAMLResponse具有saml2和saml2p前缀。
例如
<saml2p:Response xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
<saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
有方法调用
_xmlDoc.SelectSingleNode("/samlp:Response/saml:Assertion", GetNamespaceManager())
其中_xmlDoc是具有saml2和saml2p前缀且GetNamespaceManager()的SAMLResponse为
private XmlNamespaceManager GetNamespaceManager()
{
XmlNamespaceManager manager = new XmlNamespaceManager(_xmlDoc.NameTable);
manager.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);
manager.AddNamespace("saml", "urn:oasis:names:tc:SAML:2.0:assertion");
manager.AddNamespace("samlp", "urn:oasis:names:tc:SAML:2.0:protocol");
return manager;
}
为什么即使XPATH选择器是saml / samlp前缀,该方法调用也可以返回SAML2前缀元素?我对此很困惑。
P.S。我使用https://github.com/jitbit/AspNetSaml中的库来开发我的saml应用。
[[Update 14:21 30 Sep 2019 GMT + 7]我尝试将SelectSingleNode
和XmlNamespaceManager
中的前缀更改为不是saml或saml2的某些前缀。更改的结果是相同的。我认为有关xml前缀和名称空间的事情。我需要一些额外的解释。
为什么即使XPATH选择器是saml / samlp前缀,该方法调用也可以返回SAML2前缀元素?
您已经使用XML本身中用于saml2p
和saml2
前缀的相同实际名称空间声明,将这些名称空间前缀添加到名称空间管理器中。即您已经告诉名称空间管理器samlp
前缀应与XML名称空间"urn:oasis:names:tc:SAML:2.0:protocol"
相对应,XML名称空间saml2p
与samlp
前缀所对应的名称空间相同。
使用您的"urn:oasis:names:tc:SAML:2.0:protocol"
前缀的XPATH选择器将匹配声明为与saml2p
命名空间对应的any命名空间前缀。由于saml2
前缀确实存在,因此它将匹配具有该前缀的节点。
类似于saml
和"urn:oasis:names:tc:SAML:2.0:protocol"
。
确保您没有将XML名称空间前缀与XML名称空间本身混淆是非常重要的。 XML中的名称空间是字符串"urn:oasis:names:tc:SAML:2.0:assertion"
和saml2p
。前缀是标识符saml2
,samlp
,saml
和ds
(就此而言,还包括saml2p
)。前缀只是引用实际名称空间的方式。
因此,可以以相同的方式将两个不同的变量分配给相同的字符串值,因此这两个不同的变量名称可以在代码中“平均”相同的字符串值,因此两个XML名称空间前缀[C0 ]和samlp
的含义相同,与saml2
和saml
的含义相同。
因此,无论是通过XPATH还是通过API中的任何其他搜索机制来命名XML节点,重要的是namespace本身,而不是用于指定名称空间的前缀。
因此,您的XPATH表达式"/samlp:Response/saml:Assertion"
可以在XML中找到Assertion
元素,即使该表达式使用的前缀与XML文档本身中使用的前缀不同。 XPATH中的节点引用仍然与XML本身声明的名称空间相同。