当存在名称空间前缀时,无法通过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()
将因“格式错误的参考元素”而失败,应如何做到这一点?
答案 0 :(得分:36)
我们使用的方法是继承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;
}
}
答案 1 :(得分:2)
var reference = new Reference(“”); //这将签署整个文件
答案 2 :(得分:2)
应该注意,您需要使用SignedXmlWithId
对象而不是SignedXml
对象才能使用重写的GetIdElement()
方法。完成后,我就可以签署XmlElement
并绕过格式错误的参考元素错误。
答案 3 :(得分:0)
SignedXml无法将u:Id识别为有效的XML ID,并且XML签名确实要求它为XML ID。
如果您尝试使用WS-Security,可以使用Schema(http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd Id)或将DTD添加到XML片段。 (]&gt;用于XML片段)。只为你的LoadXml添加一个DTD会使SignedXml识别出Id,但由于SOAP不允许使用DTD,所以不要在你的在线SOAP中包含DTD。