电话
400 9058 355
SAML签名验证必须先对SignedInfo节点做排他性规范化(exclusive canonicalization),再用公钥验签;直接解Base64后验整个XML字节必然失败,因签名仅覆盖规范化后的SignedInfo子树。
Signature 验证不是解 Base64 后直接验字节 —— 你必须先对 SignedInfo 做排他性规范化(exclusive canonicalization),再用公钥验签。否则哪怕 XML 结构完全正确,sig.verify() 也一定失败。
contentBytes 总是 false?你当前的 verifySignature 方法传入的是整个响应 XML 的字节,但 SAML 签名只覆盖 SignedInfo 节点(含其子节点),且该节点在签名前已被按特定规则标准化(比如去掉无关空白、归一化命名空间声明)。直接传原始 XML 字符串或未规范化的节点内容,哈希值必然不匹配。
SignedInfo 是签名的“输入原文”,不是整个 Response
ds:CanonicalizationMethod@Algorithm 指定,常见为 http://www.w3.org/2001/10/xml-exc-c14n#
Node.getC14NMethod() 不支持自动识别该算法,需手动调用 org.jcp.xml.dsig.internal.dom.DOMCanonicalizer 或用 xmlsec 库xmlsec 库最稳(推荐)Apache xmlsec 是 Java 生态验证 SAML 签名的事实标准,它自动处理:CanonicalizationMethod 解析、Reference URI 解析(如 #_response123456)、Transforms(如 enveloped-signature 剔

SignatureMethod 映射(rsa-sha256 / rsa-sha1 自动适配)。import org.apache.xml.security.signature.XMLSignature; import org.apache.xml.security.transforms.Transforms; import org.w3c.dom.Document; import org.w3c.dom.Element;// 已加载 Document doc Element sigElement = (Element) doc.getElementsByTagNameNS("https://www./link/573a77b45da4e86a0fc93e5f76cc99ce#", "Signature").item(0); XMLSignature signature = new XMLSignature(sigElement, ""); boolean isValid = signature.checkSignatureValue(publicKey); // 自动做 c14n + verify
ds:SignatureValue 和 ds:SignedInfo —— xmlsec 内部已封装全部逻辑xmlsec-3.0.3.jar(适配 Java 11+)和 xmlsec-java-3.0.3.jar
SignatureMethod 很可能是 rsa-sha256,旧版 xmlsec(如 2.x)默认不支持,必须升到 3.x如果因合规或轻量要求必须不用第三方库,务必确认以下三步都严格对齐 SAML 响应中的 ds:Signature 描述:
ds:SignedInfo 元素,不是 ds:Signature 根节点signedInfoNode.getC14NMethod().canonicalizeSubtree(signedInfoNode),且参数必须设为 true(保留注释)或 false(剔除注释),取决于 CanonicalizationMethod@Algorithm 是否带 #WithComments
ds:SignatureMethod@Algorithm 提取实际算法(如 http://www.w3.org/2001/04/xmldsig-more#rsa-sha256),映射为 Java 支持的字符串(SHA256withRSA),而非硬写 RSA-SHA1
SAML 签名验证真正难的不是代码,而是对 ds:Reference 中 URI、Transforms、DigestMethod 这三者的联动理解 —— 它们共同定义了“到底哪段字节被签了”,漏掉任意一个环节,就等于在验一份假数据。
邮箱:8955556@qq.com
Q Q:8955556
本文详解如何将Go官方present工具(用于生成HTML5...
PySNMP在不同版本中对SNMP错误状态(errorSta...
time.Sleep仅阻塞当前goroutine,其他gor...
PHPfopen()创建含特殊符号的文件名失败主因是操作系统...
WooCommerce中通过代码为分组产品动态聚合子商品的属...
io.ReadFull返回io.ErrUnexpectedE...
本文详解Yii2中控制器向视图传递ActiveRecord数...
本文详解为何通过wp_set_object_terms()为...
Pytest中使用@mock.patch类装饰器会导致补丁泄...
带缓冲的channel是并发安全的FIFO队列;make(c...