DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> XML學習教程 >> XML詳解 >> XML 數字簽名的使用小技巧
XML 數字簽名的使用小技巧
編輯:XML詳解     

本文示例源代碼或素材下載

  隨著 XML 的發展, XML 的安全性越來越重要。為解決 XML 安全性的問題,W3C、OASIS 以及其標准化組織正在致力於為 XML 安全性研究標准的規范。這樣,XML 數字簽名和 XML 加密解密技術就應運而生。那麼,XML 數字簽名如何簡單高效地簽署多個 XML 文件,以及外部文件,以及如何簽署 XML 文件的片段?

  XML 數字簽名

  雖然 XML 數字簽名只是 W3C 和 IETF(Internet Engineering Task Force) 於 2002 年共同提出的草案,但 XML 簽名為任何數據提供了完整性、消息認證、以及簽名者認證服務。XML 數字簽名可以應用於任何數據對象 ( 包括 XML 文檔 ),也可以應用於一個或多個資源文件,或者資源文件的子集。XML 數字簽名格式如清單 1。

  清單 1. XML 數字簽名的格式

<Signature>
<SignedInfo>
<CanonicalizationMethod/>
<SignatureMethod/>
(<Reference (URI)?>
(<Transforms/>)?
<DigestMethod/>
<DigestValue/>
</Reference>)+
</SignedInfo>
<SignatureValue/>
(<KeyInfo/>)?
(<Object ID?/>)*
</Signature>

  XML 數字簽名如何簽署資源文件的片段?

  XML 數字簽名把 XPath 表達式作為自己的 Transform,根據 XPath 表達式來查找 XML 解析樹,最後計算出 XML 文檔中的子集。為了更簡單更快地定位 XML 文檔中的結點集合,W3C/IETF 共同提出了 XPath Filter 規范,這就是這一章節要提到的技術。

  XPath

  XPath 是針對 XML 文檔部分內容定義的語法和標准函數庫,也是 W3C 的標准。XPath 使用路徑表達式在 XML 文檔中定位導航。


 

XPath Filter

  XPath Filter 雖然只是 W3C XML 簽名工作組和 IETF 提出的草案,將來可能會被更改,甚至被其他新的方法替代。但它在 XML 簽名中使用 XPath 的思想仍然是值得借鑒的。

  XML 簽名 XPath Filter Transform 由一個或多個 XPath 結點構成。其結構如代碼清單 2.

  清單 2. XPath Filter 在 XML 數字簽名中的結構

<Transforms>
(<Transform Algorithm=”http://www.w3.org/2002/06/XMLdsig-filter2”>
(<Xpath Filter ?>
text
<Xpath>)+
</Transform>)+
</Transforms>

  XPath 結點的 text 就是 XPath 表達式 ( 其計算結果我們給它一個名字“集合 1”)。有一個 Filter 的屬性,其值為 intersect,substract 和 union,用來定義集合的操作是“交 / 差 / 並”。它的操作源 ( 即所謂的“輸入集”) 就是上一個 XPath Fitler Transform 的計算結果或其他類型 Transform 的計算結果 ( 即所謂的“輸出集”)。可以用下面的表達式來表示:

 輸入集 (intersect/substract/union) 集合 1 = 輸出集

  其輸出集又可以作為下一個 XPath Filter Transform 或其他類型 Transform 的輸入集,如此往復。

  XPath Filter 與傳統的 XPath Transform 相比,有什麼優點?

  由於 XPath Filter 計算的結果是 XML 結點集合,而不是布爾值,故 XML 簽名的一個 Transform 中就可以擁有多個 XPath 表達式,並且它們之間是順序執行的,前一個 XPath 表達式的計算結果作為下個 XPath 表達式的輸入。

  XPath Filter 在 XPath 的基礎上使用了三個基本的結合操作 ( 交集,差集,並集 ),故 XPath Filter 可以任意地拼接 XML 結點集合 ; 而傳統的 XPath Transform 只能單向地在原有的輸入 XML 結點集合中選其子集作為輸出,其輸出集合必是輸入集合的子集。

XPath Filter 只需要將輸入的 XML 結點集合與 XPath 表達式計算的結點集合進行交 / 差 / 並集計算;而傳統的 XPath Transform 需要將給定輸入的 XML 結點集合中每一個結點套入 XPath 表達式中進行計算。

  例子

  假定 XML 文檔中某一段代碼如清單 3。粗體部分是需要被過濾掉的。

  清單 3. XML 文檔片段代碼例子

<Signed>
 <Data/>
 <NotSigned1>
  <Data/>
  <Signed1>
    <Data/>
  </Signed1>
 </NotSigned1>
 <Data/>
 <Signed2>
  <NotSigned2>
   <Data/>
  </NotSigned2>
  <Data/>
 </Signed2>
</Signed>

  如果您看這段代碼仍然弄不清楚我們要簽署哪一部分,下面我們用一個文氏圖 ( 圖片 1) 來表示上面這段 XML 文檔的結點集合,其中藍色的部分是對應上面需要被過濾掉的結點集合。這樣是不是更一目了然了?

  圖 1. 清單 3 例子對應的文氏圖

XML 數字簽名的使用小技巧

  要完成以上功能,用 XPath Filter 實現,如代碼清單 4。

  清單 4. 用 XPath Filter 實現 XML 文檔片段的簽名

<dsig:Reference URI="">
<dsig:Transforms>
<dsig:Transform
Algorithm="http://www.w3.org/2002/06/XMLdsig-filter2">
<dsig:XPath Filter="subtract">
/Signed/NotSigned1</dsxp:XPath>
<dsig:XPath Filter="subtract">
/Signed/Signed2/NotSigned2</dsxp:XPath>
<dsig:XPath Filter="union">
/Signed/NotSigned1/Signed1</dsxp:XPath>
</dsig:Transform>
</dsig:Transforms>
...
</dsig:Reference>


 

用傳統的 XPath 實現,如代碼清單 5。其中,XML 簽名的引擎需要遍歷整個 XML 文檔的每個結點,如果該結點在下面那個 XPath 表達式中計算結果為真,就把該節點放入到結果集合中,表示該結點會被簽署。這樣,不僅影響性能,如果在簽署的結點集合比較復雜,編寫這些 XPath 表達式也是非常繁瑣的事情,代碼的可讀性也非常的差。

  清單 5. 用傳統的 XPath 實現

<dsig:Reference URI="">
<dsig:Transforms>
<dsig:Transform
Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
<dsig:XPath Filter="subtract">
(ancestor-or-self:: Signed and
not (ancestor-or-self:: NotSigned1
or ancestor-or-self:: NotSigned2))
or ancestor-or-self::Signed1</dsxp:XPath>
</dsig:Transform>
</dsig:Transforms>
...
</dsig:Reference>

  小節總結

  由於 XML 資源文件是一個嚴格的樹形結構,所以它的結點集合也不會有交叉的部分。這樣,對使用 XPath Filter 來說會更容易。

  除了如上面所示的用結點名字來訪問結點意外,XPath Filter 還提供了使用“id”屬性來唯一訪問 XML 的某個結點。

  這節中所舉的例子很簡單,沒有使用到 intersect 集合操作,只是起一個拋磚引玉的效果。復雜的結構留給有興趣的讀者作為練習。

  XML 數字簽名如何簽署外部文件呢?

  XML 數字簽名使用 Reference 來具體指定簽名的內容,包括摘要算法,摘要值,一個 URI 屬性,一個 Type 屬性,以及上面提到的一組 Transform,其結構見代碼清單 1。關於 Reference 就不做具體介紹了。

URI(Universal Resource IdentifIEr)統一資源標志符

  XML 數字簽名就是使用 URI 指向被簽署的對象。URI 的特點如下:

  Web 上任何資源 (Html 文檔、圖像、視頻、程序等 ) 都可以 URI 進行定位。

  URI 還支持相對路徑,用來指向同一台機器上的其他資源。

  URI 還可以指向資源的內部,其中這種 URI 由“#”結束,後面跟一個標志符。

  URI 的這些特性,給 XML 數字簽名簽署外部文件帶來了先天的優勢。下面將給出一些例子具體介紹 XML 數字簽名如何使用 URI 簽署各種資源。

  例子

  URI="http://example.com/foobar.XML"

  這個 URI 指向的是 Web 上 http://example.com/foobar.xml 的資源文件,根據它的文件擴展名,它可能是一個 XML 文檔。

  URI="http://example.com/foobar.XML#chapter1"

  這個URI指向的是Web上http://example.com/foobar.XML的資源文件中ID屬性為“chapter1”的結點。但我們更傾向使用XPath Filter Transform來獲得資源內部結點。

  URI=""

  這個 URI 指向的是當前包含這個 XML 數字簽名的 XML 文檔 ( 其中,除去注釋結點 )。

  URI="#chapter1"

  這個 URI 指向的是當前包含這個 XML 數字簽名的 XML 文檔的 ID 為“chapter1”的結點。

  小節總結

  由於 XML 數字簽名中可以擁有多個 Reference 結點,所以,XML 數字簽名可以簽署多個資源文件。

  這篇文章中所提到的 XML 文檔的“結點”指的是包含此結點,和它的子孫結點,命名空間和屬性的“樹”,此時,讀者可以把 XML 文檔理解為一個樹型結構。

用 JDK 6 實現 XML 文檔的簽名和驗證

  近期發布的 Java SE 6 提供了標准的 XML 數字簽名的接口。下面將給出第二章節和第三章節中內容的具體代碼實現。程序代碼見附件 example.XMLdsig.zip。

  附件代碼主要做的事情,就是使用 JDK 6 的 API 生成 XML 數字簽名;然後修改 XML 文件的片段以及外部 XML 文件後,驗證 XML 數字簽名;從而證明 XML 數字簽名能保證其簽署文件內容的有效性。其步驟為:

  第一步,生成 XML 數字簽名。此簽名簽署了兩個部分;其一,本地 XML 文件的片段,此本地 XML 文檔的即清單 3。其二,外部 XML 文件 http://localhost:8080/Note.XML 。

  第二步,驗證簽名,輸出驗證結果。

  第三步,修改本地 XML 文件未被簽署的部分;驗證簽名,輸出驗證結果。

  第四步,修改本地 XML 文件被簽署的部分;驗證簽名,輸出驗證結果。

  第五步,使用 HttpClIEnt 調用能修改外部文件的 Servlet,來修改外部 XML 文件 http://localhost:8080/Note.XML;驗證簽名,輸出驗證結果。

  JDK 6 如何簽署 XML 文檔片段的呢?見清單 6,首先創建一組 XPath 表達式,然後使用這一組 XPath 表達式來創建 XPath Filter 的 Transform。其構造方式還是很符合 XML 數字簽名的文法風格的。

  清單 6. 如何使用 JDK 6 API 來簽署 XML 文檔的片段

List<Transform> transformList = new ArrayList<Transform>();
// 1.1 Create ENVELOPED Transform
Transform transform = factory.newTransform(Transform.ENVELOPED,
(TransformParameterSpec) null);
transformList.add(transform);
// 1.2 Create the detail XPath expression and its filter
List<XPathType> xpathTypeList = new ArrayList<XPathType>();
XPathType xpathType = new XPathType("/Signed/NotSigned1", Filter.SUBTRACT);
xpathTypeList.add(xpathType);
    
xpathType = new XPathType("/Signed/Signed2/NotSigned2", Filter.SUBTRACT);
xpathTypeList.add(xpathType);
    
xpathType = new XPathType("/Signed/NotSigned1/Signed1", Filter.UNION);
xpathTypeList.add(xpathType);
// 1.3 Create XPath Filter Transform
XPathFilter2ParameterSpec xpathFilter2ParamSpec =
new XPathFilter2ParameterSpec(xpathTypeList);
transform = factory.newTransform(Transform.XPATH2, xpathFilter2ParamSpec);
    transformList.add(transform);

  了解了附件代碼的功能和結構後,讀者可以在自己的電腦上運行一下它。首先配置一下環境。導入 example.xmldsig 項目到 Eclipse IDE,記錄其項目的目錄;開啟 Tomcat,部署 Web 應用端口設置為 8080;並修改 server.xml 文件,設置虛擬路徑為 <Context path="" docBase="example.XMLdsig 項目所在的目錄 " debug="0" reloadable="true" ></Context>。然後即可運行。

  結束語

  整篇文章下來,我們了解了如何簽署 XML 文檔的片段,以及如何簽署外部資源文件,並且通過實踐用 JDK 6 完成了 XML 數字簽名的設計、生成、以及驗證。本文提供的代碼是一個很基本的例子,還有很多功能留待讀者去完成。

 

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved