.NET Core环境下使用SignedXml配置带前缀XML文档签名的咨询
解答
1. 如何定义ds和ec前缀
.NET 原生的SignedXml默认生成的签名节点不带自定义前缀,要实现ds前缀,需要自定义类继承SignedXml,重写GetXml()方法,遍历生成的签名相关XmlElement,统一设置前缀为ds,同时确保命名空间声明和对端要求一致。
ec是专属规范化(exc-c14n)规范的前缀,你需要手动构造InclusiveNamespaces节点:指定节点前缀为ec,命名空间为http://www.w3.org/2001/10/xml-exc-c14n#,按要求填入PrefixList属性值,再将该节点分别附加到CanonicalizationMethod和对应Transform节点的子节点位置即可。
2. 如何配置wsse:SecurityTokenReference
SignedXml默认的KeyInfo生成逻辑不支持直接输出wsse前缀的节点,你需要自定义KeyInfoClause的实现类,手动构造完整的wsse:SecurityTokenReference节点结构:
- 节点前缀设为
wsse,添加wsu:Id属性 - 内部嵌套
ds:X509Data节点,再嵌套ds:X509IssuerSerial节点 - 从签名证书中读取颁发者名称、序列号填入对应子节点
- 将自定义的KeyInfoClause实例添加到
SignedXml.KeyInfo中即可。
3. {{someValue}}标识符的来源
- 签名节点Id、KeyInfo的Id、SecurityTokenReference的wsu:Id:这三个为文档内唯一标识符,可自定义格式(常见为
Signature-随机串、KeyInfo-随机串、STR-随机串),只要保证整个XML文档内无重复即可,部分对接方会要求固定前缀,以对接文档为准。 - Reference的URI属性
#后的值:为你待签名的XML节点的Id属性值,比如要签名SOAP Body,就提前给Body节点设置唯一Id,将该Id填入此处。 - X509IssuerName、X509SerialNumber:直接从你用于签名的X509证书中读取,IssuerName取证书的
Issuer完整属性值,SerialNumber取证书的SerialNumber属性,注意不要修改序列号的大小写,必须和证书原生值一致。
额外踩坑提示
- .NET Core 3.0+、.NET 5+默认禁用SHA1算法,你需要提前在程序入口添加
AppContext.SetSwitch("System.Security.Cryptography.Xml.UseInsecureHashAlgorithms", true);开关,否则签名生成逻辑会报错。 - 所有命名空间的声明位置必须和示例一致,wsse、wsu的命名空间要声明在
wsse:Security节点上,不要提升到根节点或者Signature节点,否则规范化计算的结果会和对端不一致导致校验失败。 - 必须严格使用要求的
http://www.w3.org/2001/10/xml-exc-c14n#规范化算法,不要使用默认的C14N算法,且必须手动添加InclusiveNamespaces节点,SignedXml自带的ExcC14NTransform不会自动生成该节点。
内容的提问来源于stack exchange,提问作者Gerard Jaryczewski
相关产品推荐
相关产品推荐

