.Net Core 3.1下使用Microsoft.IdentityModel库验证SAML断言签名问题
问题原因分析
- 你当前代码的核心错误是使用了随机生成的全新RSA密钥对签名进行验证,和SAML断言签发方使用的签名私钥完全不匹配,自然无法通过验证。
RsaSecurityKey本身完全适用于该RSA-SHA256签名场景,不存在类型不匹配问题。
解决方案
你需要先从断言Signature节点的X509Data中提取签发方的公钥证书,用证书公钥生成对应SecurityKey后再执行验证,具体实现步骤如下:
- 先读取断言,从Signature.KeyInfo中提取Base64编码的X509证书内容
- 将Base64字符串转换为X509Certificate2对象,提取公钥
- 用提取到的公钥生成RsaSecurityKey,再执行签名验证
正确代码示例
using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Xml; using Microsoft.IdentityModel.Tokens.Saml; // 读取SAML XML XmlReader xmlReader = XmlReader.Create(new StringReader(xml)); SamlSerializer ser = new SamlSerializer(); var assertion = ser.ReadAssertion(xmlReader); // 从KeyInfo中提取X509证书 var x509CertificateBase64 = assertion.Signature.KeyInfo .OfType<X509RawDataKeyIdentifierClause>() .First() .GetX509RawData(); // 加载证书,提取公钥 using var cert = new X509Certificate2(x509CertificateBase64); using var rsaPublicKey = cert.GetRSAPublicKey(); if (rsaPublicKey == null) { throw new InvalidOperationException("证书中不包含RSA公钥"); } // 生成正确的SecurityKey并验证签名 var securityKey = new RsaSecurityKey(rsaPublicKey); assertion.Signature.Verify(securityKey);
额外注意事项
- 如果有预置的可信公钥,建议优先使用预置公钥进行验证,不要直接使用断言自带的证书,避免被篡改的伪造断言绕过验证
- 验证签名前建议先校验断言的Issuer、Conditions时间段等基础字段是否符合预期,再执行签名校验
- 你的SAML断言版本是1.1,确保你安装的
Microsoft.IdentityModel.Tokens.Saml包版本适配SAML1.1规范
内容的提问来源于stack exchange,提问作者Wiizl
相关产品推荐
相关产品推荐

