如何在 .Net 中解析 SAML 断言请求

发布于 2024-11-09 09:07:01 字数 1349 浏览 0 评论 0原文

我正在尝试在 .Net 中实现 SAML SSO 解决方案,但在解析断言时遇到问题。

我有一个示例断言(看起来像 byte[] 数据作为文本)和相应的 .p7b 文件。

我想从 .p7b 加载密钥并将断言解密为 XML 文档。

到目前为止,我认为我正确地读取了键:

// get the key data
byte[] certificateData = System.IO.File.ReadAllBytes("myKeys.p7b");

// decode the keys
var cms = new SignedCms(SubjectIdentifierType.IssuerAndSerialNumber);
cms.Decode(certificateData);

var samlCertificates = cms.Certificates;

然后我尝试解析断言,但遇到了问题:

// we have a keychain of X509Certificate2s, we need a collection of tokens
var certificatesAsTokens =
    from X509Certificate2 cert in samlCertificates
    select new X509SecurityToken(cert) as SecurityToken;

// get a token resolver
var tokens = new ReadOnlyCollection<SecurityToken>(
    certificatesAsTokens.ToList());
var resolver = SecurityTokenResolver.CreateDefaultSecurityTokenResolver(
    tokens, true);

// get the SAML data in an XML reader
var reader = XmlReader.Create(assertionPostStream);

// use the WS Security stuff to parse the reader
var securityToken = WSSecurityTokenSerializer.
    DefaultInstance.ReadToken(reader, resolver) as SamlSecurityToken;

最后一条语句抛出异常,指出它无法解析 XML 内容。

我认为这意味着我缺少解密断言的步骤 - 将 byte[] 作为文本转换为 SAML 格式 XML 文档。

有人知道如何添加这一步吗?我还缺少其他东西吗?

I'm trying to implement a SAML SSO solution in .Net, but I'm having a problem parsing the assertion.

I have a sample assertion (looks like byte[] data as text) and corresponding .p7b file.

I want to load the keys from the .p7b and decrypt the assertion to an XML document.

So far I think I'm reading the keys correctly:

// get the key data
byte[] certificateData = System.IO.File.ReadAllBytes("myKeys.p7b");

// decode the keys
var cms = new SignedCms(SubjectIdentifierType.IssuerAndSerialNumber);
cms.Decode(certificateData);

var samlCertificates = cms.Certificates;

Then I try to parse the assertion I get a problem:

// we have a keychain of X509Certificate2s, we need a collection of tokens
var certificatesAsTokens =
    from X509Certificate2 cert in samlCertificates
    select new X509SecurityToken(cert) as SecurityToken;

// get a token resolver
var tokens = new ReadOnlyCollection<SecurityToken>(
    certificatesAsTokens.ToList());
var resolver = SecurityTokenResolver.CreateDefaultSecurityTokenResolver(
    tokens, true);

// get the SAML data in an XML reader
var reader = XmlReader.Create(assertionPostStream);

// use the WS Security stuff to parse the reader
var securityToken = WSSecurityTokenSerializer.
    DefaultInstance.ReadToken(reader, resolver) as SamlSecurityToken;

That last statement throws an exception, stating that it can't parse the XML content.

I think this means that I'm missing a step decrypting the assertion - getting the byte[] as text converted to a SAML format XML document.

Anyone know how to add this step? Am I missing something else?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

无可置疑 2024-11-16 09:07:01

我已经弄清楚了 - 我缺少 SAML 规范的一部分。

断言作为 base64 数据发送(相当奇怪,因为它没有加密),并且在发送时进行了两次 URL 编码。

因此,添加此步骤为我们提供了一个有效的断言:

// spec says "SAMLResponse=" 
string rawSamlData = Request["SAMLResponse"];

// the sample data sent us may be already encoded, 
// which results in double encoding
if (rawSamlData.Contains('%'))
{
    rawSamlData = HttpUtility.UrlDecode(rawSamlData);
}

// read the base64 encoded bytes
byte[] samlData = Convert.FromBase64String(rawSamlData);

// read back into a UTF string
string samlAssertion = Encoding.UTF8.GetString(samlData);

身份验证仍然无法正常工作,但我现在拥有有效的 XML,因此它是不同的问题。

I've figured this out - I was missing part of the SAML specification.

The assertion is sent (rather weirdly, since it isn't encrypted) as base64 data, and it was being URL encoded twice as it was sent.

So adding this step gives us a valid assertion:

// spec says "SAMLResponse=" 
string rawSamlData = Request["SAMLResponse"];

// the sample data sent us may be already encoded, 
// which results in double encoding
if (rawSamlData.Contains('%'))
{
    rawSamlData = HttpUtility.UrlDecode(rawSamlData);
}

// read the base64 encoded bytes
byte[] samlData = Convert.FromBase64String(rawSamlData);

// read back into a UTF string
string samlAssertion = Encoding.UTF8.GetString(samlData);

The authentication still isn't working, but I now have valid XML so it's a different problem.

只涨不跌 2024-11-16 09:07:01

这是我的工作源代码:

            byte[] samlData = Convert.FromBase64String(samlresponse);

            var decompressedStream = SAMLUtility.Decompress(samlData);
            StreamReader reader = new StreamReader(decompressedStream);
            var decodedSaml = reader.ReadToEnd();

            var serializer = new XmlSerializer(typeof(Response));
            Response samlResponse;

            using (TextReader reader1 = new StringReader(decodedSaml))
            {
                samlResponse = (Response)serializer.Deserialize(reader1);
            }

            if (samlResponse.Status.StatusCode.Value.Contains("Success"))
                return samlResponse;
            else
                return null;

This is my working source code :

            byte[] samlData = Convert.FromBase64String(samlresponse);

            var decompressedStream = SAMLUtility.Decompress(samlData);
            StreamReader reader = new StreamReader(decompressedStream);
            var decodedSaml = reader.ReadToEnd();

            var serializer = new XmlSerializer(typeof(Response));
            Response samlResponse;

            using (TextReader reader1 = new StringReader(decodedSaml))
            {
                samlResponse = (Response)serializer.Deserialize(reader1);
            }

            if (samlResponse.Status.StatusCode.Value.Contains("Success"))
                return samlResponse;
            else
                return null;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文