[英]How to parse a SAML assertion request in .Net
我正在嘗試在.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 文檔。
有人知道如何添加此步驟嗎? 我還缺少其他東西嗎?
我已經弄明白了 - 我錯過了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,因此這是一個不同的問題。
這是我的工作源代碼:
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;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.