我正在编写一个 SAML 2.0 响应解析器来处理 ASP.Net 中的 POST 身份验证(在 C# 和 MVC 中,但这不太相关)。
所以我有一个.p7b
文件来验证,它可以读入X509Certificate2Collection
一个示例断言 - 一个 base 64 编码的 SAML 响应。
理想情况下,我想使用内置的WSSecurityTokenSerializer
,但是失败了,所以我正在寻找一种可行的方法。
我正在直接阅读 XML:
// get the base 64 encoded SAML
string samlAssertionRaw = GetFromHttpRequest();
// load a new XML document
var assertion = new XmlDocument { PreserveWhitespace = true };
assertion.LoadXml(samlAssertionRaw);
// use a namespace manager to avoid the worst of xpaths
var ns = new XmlNamespaceManager(assertion.NameTable);
ns.AddNamespace("samlp", @"urn:oasis:names:tc:SAML:2.0:protocol");
ns.AddNamespace("saml", @"urn:oasis:names:tc:SAML:2.0:assertion");
ns.AddNamespace("ds", SignedXml.XmlDsigNamespaceUrl);
// get the signature XML node
var signNode = assertion.SelectSingleNode(
"/samlp:Response/saml:Assertion/ds:Signature", ns);
// load the XML signature
var signedXml = new SignedXml(assertion.DocumentElement);
signedXml.LoadXml(signNode as XmlElement);
// get the certificate, basically:
// signedXml.KeyInfo.OfType<KeyInfoX509Data>().First().
// Certificates.OfType<X509Certificate2>().First()
// but with added checks
var certificate = GetFirstX509Certificate(signedXml);
// check the key and signature match
if (!signedXml.CheckSignature(certificate, true))
{
throw new SecurityException("Signature check failed.");
}
// go on and read the SAML attributes from the XML doc
这很有效,但它所做的只是检查X509Certificate2
SAML 响应中的签名和公钥是否匹配。它不会以任何方式验证它来自谁,我需要在接受 SAML 身份验证之前这样做。
似乎有两种方法可以检查在 SAML 响应中找到的证书 - 我可以这样做,certificate.Verify()
或者我可以使用签名进行检查signedXml.CheckSignature(certificate, false)
。
然而,两者都返回假。
我认为这是因为他们正在根据机器商店或可能在线进行检查(我不知道如何检查)。我想对照X509Certificate2Collection
从文件中检索到的内容来检查它们.p7b
——机器上注册的证书应该被忽略,只.p7b
检查证书。
似乎没有任何方法可以将 传递X509Certificate2Collection
给Verify
orCheckSignature
方法。
这是对 SAML 响应进行的正确检查吗?
有什么方法可以.p7b
按照我想要的方式使用证书吗?