利用WSE 加密SOAP報文(7)

給收到的報文解密<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

當收到一個由X.509證書加密後的報文後,SoapInputFilter會自動嘗試使用用戶密鑰儲存室的私有密鑰來進行解密,當然,這個需要告訴WSE運行時哪裏可以找到這個證書的額外配置信息。這個信息由應用程序配置文件的Security元素所指定,這個例子在客戶端上的應用程序配置文件是App.config。對於 X.509加密,你只需要添加一個x509子節點,內容和下面一樣就可以了

<x509

  storeLocation="CurrentUser"

  verifyTrust="true"

  allowTestRoot="false" />

在我的例子中,我將x509節點的storeLocation屬性設爲CurrentUser,假設證書在當前用戶的證書儲存室裏,當我使用了來自CA的受信任證書之後,我也將verifyTrust設爲true了。這些屬性還能夠用WSE的設置工具來修改。利用這些信息,WSE能夠得到報文中證書的私有密鑰,還能用這個來給對稱性會話密鑰解密,解密後的內容到頭來還要給報文正文解密。

選擇用於解密的報文元素

當整個消息正文由默認設置給加密後,WSE能被用來給SOAP報文內的特定元素加密;唯一的問題是,在Security頭元素那的元素不能被加密。你還可以加密嵌套的元素,

在這個例子服務中,我修改了GetXmlDocument方法用的X.509版本,用一個基於X.509的安全Token來同時給EncryptedSubResponse和它的EncryptedResponse父節點進行數字化加密,返回的XML文檔如下:

<Response>

  <NotEncrypted>

    迴應報文的這裏沒有必要被加密

  </NotEncrypted>

  <EncryptedResponse>

    <EncryptedSubResponse>

      這裏是敏感數據.

    </EncryptedSubResponse>

  </EncryptedResponse>

</Response>

爲了加密一個元素,它需要一個wsu:Id屬性,以便當XML被序列化後引用可以加到該節點上了。命名空間wsu被定義爲:

xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility

爲了完成這個,我將這個XML加到一個新的XML文檔,然後通過.NET框架支持的Microsoft XML文檔對象模型(DOM)給它添加一個Id屬性,此外還需要將配件System.Xml加入到工程引用裏面,加上下面的話:

using System.Xml;

using System.Xml.Serialization;

當我將多個Id屬性加到嵌套的元素上後,我由EncryptedSubResponse元素開始依次遍歷到它的父節點EncryptedResponse,如下:

 

string [] myId = {"Id:" + Guid.NewGuid(),"Id:" + Guid.NewGuid()};

 

 

//創建一個用於返回XML的XML文檔

XmlDocument myDoc = new XmlDocument();

myDoc.LoadXml("<Response>" +

  "<NotEncrypted>迴應報文的這裏沒有必要加密" +

  "</NotEncrypted>" +

  "<EncryptedResponse>" +

  "<EncryptedSubResponse>" +

  "這裏是敏感數據. " +

  "</EncryptedSubResponse>" +

  "</EncryptedResponse>" +

  "</Response>");

 

//得到EncryptedSubResponse節點

XmlNode    = myDoc.FirstChild.LastChild.FirstChild;

 

 

//向上遍歷元素,添加兩個Id屬性

//向上保證內部的多數元素可以優先被加密

//否則我們會得到一個異常

for (int i=0;i<myId.Length;i++)

{

 

  //創建新的Id屬性

  string wsu = "http://schemas.xmlsoap.org/ws/2002/07/utility";

  XmlNode myAttr = myDoc.CreateNode(XmlNodeType.Attribute, "wsu",

    "Id", wsu);

  myAttr.Value = myId[i];

 

  //將屬性添加到文檔

  root.Attributes.SetNamedItem(myAttr);

  root = root.ParentNode; // 移動到父節點

}

假設我早就用我前面的邏輯得到了來自X.509證書的安全記號,我將這些引用添加到EncryptedData元素,如下:

 

//循環遍歷Id值,將其添加到新的EncryptedData元素上

for (int i=0;i<myId.Length;i++)

{

  //創建一個新的頭,”#”是的前綴,用來保證相關的URI能夠引用到頭

  EncryptedData myEncHeader = new EncryptedData(myToken, "#"+myId[i]);

  //添加一個新的頭到集合中

  myContext.Security.Elements.Add(myEncHeader);

}  

//返回加密數據

return myDoc;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章