我一直在嘗試讓 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 關注
- 129 瀏覽
添加回答
舉報
0/150
提交
取消