在 IClientMessageInspector 实现中将 Id 属性添加到 soap body 元素
Add Id attribute to soap body element in IClientMessageInspector implementation
我有一些代码可以将 X509 证书插入到 soap header 中,似乎工作正常。
private Message SignMessage(Message request)
{
var doc = new XmlDocument();
var sb = new StringBuilder();
var a = request.CreateBufferedCopy(Int32.MaxValue);
XmlWriter writer = XmlWriter.Create(sb);
a.CreateMessage().WriteMessage(writer);
writer.Close();
doc.LoadXml(sb.ToString());
//This is needed or added the Reference.Uri to the signed Xml will fail
var attr = doc.CreateAttribute("Id");
attr.Value = "MyId";
doc.GetElementsByTagName("s:Body")[0].Attributes.SetNamedItem(attr);
var signed = new SignedXml(doc);
var store = new X509Store(StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
var cert = store.Certificates.Find(X509FindType.FindBySerialNumber, "6e 3c 63 19 bf 19 4b 6d 1b b0 88 1e 57 f0 16 00", true)[0];
signed.SigningKey = cert.PrivateKey;
//Set Reference.Uri
Reference reference = new Reference();
reference.Uri = "#MyId";
KeyInfo keyInfo = new KeyInfo();
KeyInfoX509Data keyInfoX509Data = new KeyInfoX509Data(cert);
keyInfoX509Data.AddSubjectName(cert.IssuerName.Name);
keyInfo.AddClause(keyInfoX509Data);
signed.KeyInfo = keyInfo;
//Add reference to signed xml
signed.AddReference(reference);
signed.ComputeSignature();
XmlElement signature = signed.GetXml();
request = a.CreateMessage();
var element = doc.GetElementsByTagName("s:Header")[0];
element.AppendChild(doc.ImportNode(signature, true));
var xSig = XElement.Parse(element.OuterXml);
foreach (var xElement in xSig.Elements())
{
if (xElement.Name.LocalName == "Signature")
{
//Add signature to header here
var sigDoc = new XmlDocument();
sigDoc.Load(xElement.CreateReader());
var list = new XmlNode[sigDoc.ChildNodes.Item(0).ChildNodes.Count];
for (int x = 0; x < sigDoc.ChildNodes.Item(0).ChildNodes.Count; x++)
{
list[x] = sigDoc.ChildNodes.Item(0).ChildNodes.Item(x);
}
MessageHeader header = MessageHeader.CreateHeader(xElement.Name.LocalName,
xElement.Name.Namespace.NamespaceName, list);
request.Headers.Add(header);
}
}
return request;
}
我现在遇到的问题是如何使用该证书来签署 soap body 元素。我需要 soap body 元素来匹配 Reference.Uri
中设置的 MyId
,但似乎无法对 body 标记进行任何更改。我似乎能做的就是更改 body 的内容,而不是向 body 标签本身添加内容。
所以目前看起来是这样的:
<s:Body>
但我需要它看起来像这样:
<s:Body Id="MyId">
有什么方法可以通过操纵消息来做到这一点?
Message.CreateMessage(XmlDictionaryReader, Int32, MessageVersion) 解决了问题。操作 xml,然后从 xml.
创建新消息
我有一些代码可以将 X509 证书插入到 soap header 中,似乎工作正常。
private Message SignMessage(Message request)
{
var doc = new XmlDocument();
var sb = new StringBuilder();
var a = request.CreateBufferedCopy(Int32.MaxValue);
XmlWriter writer = XmlWriter.Create(sb);
a.CreateMessage().WriteMessage(writer);
writer.Close();
doc.LoadXml(sb.ToString());
//This is needed or added the Reference.Uri to the signed Xml will fail
var attr = doc.CreateAttribute("Id");
attr.Value = "MyId";
doc.GetElementsByTagName("s:Body")[0].Attributes.SetNamedItem(attr);
var signed = new SignedXml(doc);
var store = new X509Store(StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
var cert = store.Certificates.Find(X509FindType.FindBySerialNumber, "6e 3c 63 19 bf 19 4b 6d 1b b0 88 1e 57 f0 16 00", true)[0];
signed.SigningKey = cert.PrivateKey;
//Set Reference.Uri
Reference reference = new Reference();
reference.Uri = "#MyId";
KeyInfo keyInfo = new KeyInfo();
KeyInfoX509Data keyInfoX509Data = new KeyInfoX509Data(cert);
keyInfoX509Data.AddSubjectName(cert.IssuerName.Name);
keyInfo.AddClause(keyInfoX509Data);
signed.KeyInfo = keyInfo;
//Add reference to signed xml
signed.AddReference(reference);
signed.ComputeSignature();
XmlElement signature = signed.GetXml();
request = a.CreateMessage();
var element = doc.GetElementsByTagName("s:Header")[0];
element.AppendChild(doc.ImportNode(signature, true));
var xSig = XElement.Parse(element.OuterXml);
foreach (var xElement in xSig.Elements())
{
if (xElement.Name.LocalName == "Signature")
{
//Add signature to header here
var sigDoc = new XmlDocument();
sigDoc.Load(xElement.CreateReader());
var list = new XmlNode[sigDoc.ChildNodes.Item(0).ChildNodes.Count];
for (int x = 0; x < sigDoc.ChildNodes.Item(0).ChildNodes.Count; x++)
{
list[x] = sigDoc.ChildNodes.Item(0).ChildNodes.Item(x);
}
MessageHeader header = MessageHeader.CreateHeader(xElement.Name.LocalName,
xElement.Name.Namespace.NamespaceName, list);
request.Headers.Add(header);
}
}
return request;
}
我现在遇到的问题是如何使用该证书来签署 soap body 元素。我需要 soap body 元素来匹配 Reference.Uri
中设置的 MyId
,但似乎无法对 body 标记进行任何更改。我似乎能做的就是更改 body 的内容,而不是向 body 标签本身添加内容。
所以目前看起来是这样的:
<s:Body>
但我需要它看起来像这样:
<s:Body Id="MyId">
有什么方法可以通过操纵消息来做到这一点?
Message.CreateMessage(XmlDictionaryReader, Int32, MessageVersion) 解决了问题。操作 xml,然后从 xml.
创建新消息