使用WSE 加密SOAP報(bào)文(7)
發(fā)表時(shí)間:2024-06-19 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]給收到的報(bào)文解密當(dāng)收到一個(gè)由X.509證書加密后的報(bào)文后,SoapInputFilter會(huì)自動(dòng)嘗試使用用戶密鑰儲(chǔ)存室的私有密鑰來進(jìn)行解密,當(dāng)然,這個(gè)需要告訴WSE運(yùn)行時(shí)哪里可以找到這個(gè)證書的額外配置信息。這個(gè)信息由應(yīng)用程序配置文件的Security元素所指定,這個(gè)例子在客戶端上的應(yīng)用程序配置文件是...
給收到的報(bào)文解密
當(dāng)收到一個(gè)由X.509證書加密后的報(bào)文后,SoapInputFilter會(huì)自動(dòng)嘗試使用用戶密鑰儲(chǔ)存室的私有密鑰來進(jìn)行解密,當(dāng)然,這個(gè)需要告訴WSE運(yùn)行時(shí)哪里可以找到這個(gè)證書的額外配置信息。這個(gè)信息由應(yīng)用程序配置文件的Security元素所指定,這個(gè)例子在客戶端上的應(yīng)用程序配置文件是App.config。對(duì)于 X.509加密,你只需要添加一個(gè)x509子節(jié)點(diǎn),內(nèi)容和下面一樣就可以了
<x509
storeLocation="CurrentUser"
verifyTrust="true"
allowTestRoot="false" />
在我的例子中,我將x509節(jié)點(diǎn)的storeLocation屬性設(shè)為CurrentUser,假設(shè)證書在當(dāng)前用戶的證書儲(chǔ)存室里,當(dāng)我使用了來自CA的受信任證書之后,我也將verifyTrust設(shè)為true了。這些屬性還能夠用WSE的設(shè)置工具來修改。利用這些信息,WSE能夠得到報(bào)文中證書的私有密鑰,還能用這個(gè)來給對(duì)稱性會(huì)話密鑰解密,解密后的內(nèi)容到頭來還要給報(bào)文正文解密。
選擇用于解密的報(bào)文元素
當(dāng)整個(gè)消息正文由默認(rèn)設(shè)置給加密后,WSE能被用來給SOAP報(bào)文內(nèi)的特定元素加密;唯一的問題是,在Security頭元素那的元素不能被加密。你還可以加密嵌套的元素,
在這個(gè)例子服務(wù)中,我修改了GetXmlDocument方法用的X.509版本,用一個(gè)基于X.509的安全Token來同時(shí)給EncryptedSubResponse和它的EncryptedResponse父節(jié)點(diǎn)進(jìn)行數(shù)字化加密,返回的XML文檔如下:
<Response>
<NotEncrypted>
回應(yīng)報(bào)文的這里沒有必要被加密
</NotEncrypted>
<EncryptedResponse>
<EncryptedSubResponse>
這里是敏感數(shù)據(jù).
</EncryptedSubResponse>
</EncryptedResponse>
</Response>
為了加密一個(gè)元素,它需要一個(gè)wsu:Id屬性,以便當(dāng)XML被序列化后引用可以加到該節(jié)點(diǎn)上了。命名空間wsu被定義為:
xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility
為了完成這個(gè),我將這個(gè)XML加到一個(gè)新的XML文檔,然后通過.NET框架支持的Microsoft XML文檔對(duì)象模型(DOM)給它添加一個(gè)Id屬性,此外還需要將配件System.Xml加入到工程引用里面,加上下面的話:
using System.Xml;
using System.Xml.Serialization;
當(dāng)我將多個(gè)Id屬性加到嵌套的元素上后,我由EncryptedSubResponse元素開始依次遍歷到它的父節(jié)點(diǎn)EncryptedResponse,如下:
string [] myId = {"Id:" + Guid.NewGuid(),"Id:" + Guid.NewGuid()};
//創(chuàng)建一個(gè)用于返回XML的XML文檔
XmlDocument myDoc = new XmlDocument();
myDoc.LoadXml("<Response>" +
"<NotEncrypted>回應(yīng)報(bào)文的這里沒有必要加密" +
"</NotEncrypted>" +
"<EncryptedResponse>" +
"<EncryptedSubResponse>" +
"這里是敏感數(shù)據(jù). " +
"</EncryptedSubResponse>" +
"</EncryptedResponse>" +
"</Response>");
//得到EncryptedSubResponse節(jié)點(diǎn)
XmlNode = myDoc.FirstChild.LastChild.FirstChild;
//向上遍歷元素,添加兩個(gè)Id屬性
//向上保證內(nèi)部的多數(shù)元素可以優(yōu)先被加密
//否則我們會(huì)得到一個(gè)異常
for (int i=0;i<myId.Length;i++)
{
//創(chuàng)建新的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; // 移動(dòng)到父節(jié)點(diǎn)
}
假設(shè)我早就用我前面的邏輯得到了來自X.509證書的安全記號(hào),我將這些引用添加到EncryptedData元素,如下:
//循環(huán)遍歷Id值,將其添加到新的EncryptedData元素上
for (int i=0;i<myId.Length;i++)
{
//創(chuàng)建一個(gè)新的頭,”#”是的前綴,用來保證相關(guān)的URI能夠引用到頭
EncryptedData myEncHeader = new EncryptedData(myToken, "#"+myId[i]);
//添加一個(gè)新的頭到集合中
myContext.Security.Elements.Add(myEncHeader);
}
//返回加密數(shù)據(jù)
return myDoc;