在IClientMessageInspector实现中将Id属性添加到soap body元素

时间:2015-06-10 11:36:55

标签: c# .net wcf soap

我有一些代码将X509证书插入到肥皂标题中,似乎可以正常工作。

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元素来匹配MyId中设置的Reference.Uri,但似乎无法对body标签进行任何更改。我似乎能够做的就是改变身体的内容,而不是在身体标签本身添加一些东西。

所以目前它看起来像是这样:

<s:Body>

但我需要它看起来像这样:

<s:Body Id="MyId">

我可以通过操纵消息来做到这一点吗?

1 个答案:

答案 0 :(得分:0)

Message.CreateMessage(XmlDictionaryReader, Int32, MessageVersion)解决了这个问题。操纵xml,然后从xml创建新消息。