代码之家  ›  专栏  ›  技术社区  ›  Russ

引用元素格式不正确

  •  9
  • Russ  · 技术社区  · 10 年前

    我试图将引用添加到我的安全标头,但遇到了一个相当常见的错误:

    引用元素格式不正确

    我尝试了以下方法,结果相似:

    1. 通过传入 ID 元素的 URI Reference 对象
    2. 通过 XmlElement 对象 参考 通过 LoadXml() 方法我正在检索 Xml元素 通过使用重载 GetIdElement 在上找到 this StackOverflow post .

    当我将空字符串作为 URI 这个 ComputeSignature() 方法 SignedXml 工作正常。然而,我需要添加最多3个对Security Header的引用。

    更新#1
    幸亏 this blog post ,我能够从中创建简化版本,我相信导致我问题的原因是使用 Namespace 属性和前缀。

    更新#2
    似乎 Id 的属性 <Timestamp> 元素导致发生此错误。

    更新#3
    我想我已经开始工作了。请看下面我的回答帖子。

    工作样品:
    请注意 Id XAttribute 定义的命名空间不起作用;而 Id X属性 如果未定义命名空间,则不起作用。

    private void CreateSecurityAndTimestampXML(string fileName)
    {
        TimestampID = "TS-E" + GUID.NewGuid();
        DateTime SecurityTimestampUTC = DateTime.UtcNow;
    
        XDocument xdoc = new XDocument(
            new XElement(wsse + "Security",
                new XAttribute(XNamespace.Xmlns + "wsse", wsse.NamespaceName),
                new XAttribute(XNamespace.Xmlns + "wsu", wsu.NamespaceName),
                new XElement(wsu + "Timestamp",
                    // new XAttribute(wsu + "Id", TimestampID), // <-- Does Not Work
                    new XAttribute("Id", TimestampID), // <-- Works
                    new XElement(wsu + "Created", SecurityTimestampUTC.ToString(_timestampFormat)),
                    new XElement(wsu + "Expires", SecurityTimestampUTC.AddMinutes(10).ToString(_timestampFormat))
                )
            )
        );
    
        using (XmlTextWriter tw = new XmlTextWriter(fileName, new UTF8Encoding(false)))
        {
            xdoc.WriteTo(tw);
        }
    }
    
    // Snippet
    string[] elements = { TimestampID };
    
    foreach (string s in elements)
    {
        Reference reference = new Reference()
        {
            Uri = "#" + s
        };
    
        XmlDsigExcC14NTransform env = new XmlDsigExcC14NTransform();
        env.InclusiveNamespacesPrefixList = _includedPrefixList;
        reference.AddTransform(env);
    
        xSigned.AddReference(reference);
    }
    
    // Add Key Info Here.
    
    // Compute the Signature.
    xSigned.ComputeSignature();
    
    1 回复  |  直到 9 年前
        1
  •  8
  •   Community Mohan Dere    9 年前

    至少在目前看来,实现这一目标的答案如下。

    而不是使用 SignedXml 类,新建 SignedXmlWithId 对象,使用详细的类 here .

    // Create a new XML Document.
    XmlDocument xdoc = new XmlDocument();
    
    xdoc.PreserveWhitespace = true;
    
    // Load the passed XML File using its name.
    xdoc.Load(new XmlTextReader(fileName));
    
    // Create a SignedXml Object.
    //SignedXml xSigned = new SignedXml(xdoc);
    SignedXmlWithId xSigned = new SignedXmlWithId(xdoc); // Use this class instead of the SignedXml class above.
    
    // Add the key to the SignedXml document.
    xSigned.SigningKey = cert.PrivateKey;
    xSigned.Signature.Id = SignatureID;
    xSigned.SignedInfo.CanonicalizationMethod = 
            SignedXml.XmlDsigExcC14NWithCommentsTransformUrl;
    
    //Initialize a variable to contain the ID of the Timestamp element.
    string elementId = TimestampID;
    
    Reference reference = new Reference()
    {
        Uri = "#" + elementId
    };
    
    XmlDsigExcC14NTransform env = new XmlDsigExcC14NTransform();
    env.InclusiveNamespacesPrefixList = _includedPrefixList;
    reference.AddTransform(env);
    
    xSigned.AddReference(reference);
    
    // Add Key Information (omitted)
    
    // Compute Signature
    xSigned.ComputeSignature();