使用SignXML验证SAML响应时签名/证书校验失败如何解决?
证书链错误解决方案
- 先确认证书格式:signxml要求的是PEM格式证书,你拿到的.cer文件大概率是DER二进制格式,需要先转换为PEM格式:
# 转换DER格式CER到PEM openssl x509 -inform DER -in 第三方提供的第一个证书.cer -out cert1.pem openssl x509 -inform DER -in 第三方提供的第二个证书.cer -out cert2.pem
- 合并证书链:将两个PEM证书合并为一个文件,顺序为根证书在前,中间/叶子证书在后,保存为
trusted_chain.pem。 - 验证证书匹配:提取SAML响应中
<X509Certificate>节点的内容,和你转换后的叶子证书内容比对,确保一致,避免拿错证书。
签名校验失败解决方案
你当前的签名错误90%概率是因为提前用ElementTree解析了XML:XML签名校验依赖原始内容的规范化结果,用ET解析后再传入会改变XML的空格、命名空间等结构,导致哈希计算不匹配。不要解析XML,直接传入base64解码后的原始字节即可。
另外要注意:Redirect绑定返回的SAMLResponse参数会做一层URL编码,需要先做URL解码再做Base64解码,否则解码出来的XML内容是错误的。
修正后的代码示例
import base64 from urllib.parse import unquote from signxml import XMLVerifier # 1. 处理拿到的SAML token:先URL解码,再Base64解码,不要解析XML raw_saml_param = "你从重定向请求中拿到的SAMLResponse参数原始值" url_decoded_token = unquote(raw_saml_param) xml_raw_bytes = base64.b64decode(url_decoded_token) # 2. 直接传入原始字节校验 trusted_cert_path = "./trusted_chain.pem" verify_result = XMLVerifier().verify( data=xml_raw_bytes, ca_pem_file=trusted_cert_path ) # 校验通过后可以从verify_result中提取断言信息 assertion = verify_result.get_assertion()
临时调试方案
如果证书链问题暂时无法解决,可以先提取SAML中自带的证书做签名校验,确认签名本身没问题后再处理证书信任问题:
# 先从SAML中提取自带的证书内容,包装为PEM格式 saml_embed_cert = "-----BEGIN CERTIFICATE-----\n" + "SAML中X509Certificate节点的base64内容" + "\n-----END CERTIFICATE-----" verify_result = XMLVerifier().verify( data=xml_raw_bytes, x509_cert=saml_embed_cert, validate_signature_certificate=False # 临时关闭证书链校验,仅验证签名是否正确 )
内容的提问来源于stack exchange,提问作者Bli
相关产品推荐
相关产品推荐

