23

当存在命名空间前缀时,无法通过 Id 属性对元素进行签名:

void Main()
{
    var doc = new XmlDocument();
    doc.LoadXml("<root xmlns:u=\"myuri\"><test u:Id=\"_0\">Zebra</test></root>");

    SignedXml signedXml = new SignedXml(doc);
    signedXml.SigningKey = new RSACryptoServiceProvider();

    Reference reference = new Reference("#_0");
    signedXml.AddReference(reference);

    signedXml.ComputeSignature();
}

ComputeSignature()此处将因“格式错误的参考元素”而失败,该怎么做?

4

4 回答 4

51

我们使用的方法是子System.Security.Cryptography.Xml.SignedXml类化...

public class SignedXmlWithId : SignedXml
{
    public SignedXmlWithId(XmlDocument xml) : base(xml)
    {
    }

    public SignedXmlWithId(XmlElement xmlElement) 
        : base(xmlElement)
    {       
    }

    public override XmlElement GetIdElement(XmlDocument doc, string id)
    {
        // check to see if it's a standard ID reference
        XmlElement idElem = base.GetIdElement(doc, id);

        if (idElem == null)
        {
            XmlNamespaceManager nsManager = new XmlNamespaceManager(doc.NameTable);
            nsManager.AddNamespace("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");

            idElem = doc.SelectSingleNode("//*[@wsu:Id=\"" + id + "\"]", nsManager) as XmlElement;
        }

        return idElem;
    }
}
于 2011-06-24T12:35:14.113 回答
3

var 参考 = 新参考(“”);// 这将签署整个文档

于 2011-02-24T01:20:55.260 回答
2

应该注意的是,您需要使用SignedXmlWithIdobject 而不是SignedXmlobject 才能使用覆盖的GetIdElement()方法。一旦我这样做了,我就能够签署XmlElement并绕过Malformed Reference Element错误。

在此处查看我关于此主题的帖子

于 2016-03-02T22:44:08.047 回答
0

SignedXml 不将 u:Id 识别为有效的 XML ID,并且 XML 签名确实要求它是 XML ID。

您可以使用 Schema(如果您尝试使用 WS-Security Id,则为 http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd)或将 DTD 添加到 XML 片段。( ]> 用于 XML 片段)。将 DTD 添加到您的 LoadXml 将使 SignedXml 识别 Id,但由于 SOAP 不允许 DTD,因此不要将 DTD 包含在您的在线 SOAP 中。

于 2011-03-25T15:21:07.957 回答