我一直在尝试让 xmllib 通过 合作并验证 xmldsig<Signature>元素DOMDocument,但无论我如何将元素扔给它,它都会不断产生虚假错误。显然,由于而无法<Signature>成为 root 。我无法正确设置根上的属性:尝试验证结果:DOMDocumentxmlnsElement 'Signature': No matching global declaration available for the validation root. 我认为这可能是因为模式旨在“包含”,您毕竟想要签署“某些东西”,而不仅仅是本身签名。因此,通过创建这个:<?xml version="1.0"?><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" version="1.0" elementFormDefault="qualified"><xs:import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="xmldsig-core-schema.xsd" /><xs:element name="root"> <xs:complexType> <xs:sequence> <xs:element ref="ds:Signature" /> </xs:sequence> </xs:complexType></xs:element></xs:schema>我现在可以拥有虚拟元素的包含签名。我意识到 PHP XML 处理相当糟糕,没有一个工具真正工作得那么好。然而,一旦它实际上正确地将事情交给 xmllint,这样做应该没有问题。其他答案建议也添加 XPath,但我想保持 KISS;尽可能少地使用 PHP 库。通过几百行代码的欺骗,我让它配合并将<Signature>xml 文件的一部分包装到一个<root>元素内的普通测试文件中。我认为它正在做一些事情来破坏文档中的名称空间。$myDocument->saveXML();失败后调用$myDocument->schemaValidate();会返回一个特殊的结果:Element 'Signature': This element is not expected. Expected is ( {http://www.w3.org/2000/09/xmldsig#}Signature ).当 xml 看起来像这样时(我已经添加了格式;实际情况是未格式化的;尽管空格不应该很重要):<?xml version="1.0"?><root> <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> (... omitted crypto ...) </Signature></root>从我对它所做的阅读来看,该错误应该意味着<Signature> 元素上的命名空间是错误的。但在这里,它明确地明确指定为xmlns错误消息所期望的内容。那么,这里出了什么问题呢?附录:准备签名进行验证的代码(在任意文档中)看起来像这样。这是一个复杂的版本,我添加了一个“根”元素,而不是直接使用模式,请参阅下面的我的答案,结果证明这是不必要的,尽管这是一个很好的测试,就像在您想要的更复杂的场景中一样要在对 libxml 的一次调用中验证签名的内容,这是一件有效的事情:
1 回答
MM们
TA贡献1886条经验 获得超2个赞
PHP 就是问题所在。它存在微妙的错误,并且不会/不能正确理解以编程方式创建的文档中的 XML 名称空间。
添加/编辑 DOMDocument 元素的方法有多种,其中一些/大部分可能会导致元素E位于某个名称空间X中,当您仅查看 XML 输出时,但 DOMDocument 对象认为它位于名称空间Y中。即使您只使用提供的函数而不访问对象的内部,也可能使它们处于不一致的状态。在某些情况下,如果您想要特定格式的命名空间(由于规范化问题)甚至是不可避免的。
替换该行代码
$myDocument->schemaValidate();
和
$myDocument->loadXML($myDocument->saveXML()); $myDocument->schemaValidate();
并且验证错误应该消失。无论哪种方式(使用xsd
包含的自定义或直接使用 xmldsig 验证文件)都应该有效。
虽然该错误被视为“不是错误”,但它确实是一个问题,因为DOMDOcument
实际上不会使用xmlns
属性输出确切的语法,而是使用前缀表示法(如果您使用createElementNS()
. (虽然语法上可能是相同的,但没有人理解 xml 命名空间,因此接受您的 XML 的人可能希望它与示例完全相同,即:使用 ,而xmlns
不是使用元素ds:Signature
)。
相反, usingDOMElement::setAttributeNS($currentNS, 'xmlns', $subElementNS)
会输出默认命名空间标记,但不会使用新命名空间正确递归地标记元素下的编程实体。
- 1 回答
- 0 关注
- 98 浏览
添加回答
举报
0/150
提交
取消