gpt4 book ai didi

c# - 如何使用 C# 签署 SAMLResponse 和加密断言?

转载 作者:行者123 更新时间:2023-12-04 17:49:07 27 4
gpt4 key购买 nike

我有一个 IDP,它生成带有签名断言的 SAMLResponse。我不打算添加生成的 XML 文件的示例,因为它会使问题太长。但如果这真的有帮助,请告诉我,我会添加它。

SP 要求对断言进行加密并对响应进行签名,但目前情况并非如此。经过研究,我找不到如何去做,我会发布一些我尝试过的代码,但老实说我有点无能为力,我尝试的一切都没有成功。

问题是,我如何签署响应并加密断言?

以下是响应的创建和签名方式:

public class SAML
{
private const int tokenLifetime = 30;
private const string issuer = "https://some.domain/IdP";
private const string CertificateSerialNumber = "XXXXXXXXXXXXX";

private static string _RequestId;
private static string _RequestIssueInstant;
private static string _RequestProviderName;
private static string _RequestACS;
private static Dictionary<string, string> _claimDescriptors = new Dictionary<string, string>();


public static string CreateSamlResponse(string RequestId, string RequestIssueInstant, string RequestProviderName, string RequestACS, Dictionary<string,string> claimDescriptors)
{
_RequestId = RequestId;
_RequestIssueInstant = RequestIssueInstant;
_RequestProviderName = RequestProviderName;
_RequestACS = RequestACS;
_claimDescriptors = claimDescriptors;

var claims = CreateClaims();
var tokenHandler = new Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler();
var token = CreateToken(claims, tokenHandler);

return CreateSamlResponseXml(tokenHandler, token);
}

private static Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityToken CreateToken(IEnumerable<Microsoft.IdentityModel.Claims.Claim> claims,
Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler tokenHandler)
{
var descriptor = CreateTokenDescriptor(claims);
var token = tokenHandler.CreateToken(descriptor) as Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityToken;

AddAuthenticationStatement(token);
AddConfirmationData(token);

return token;
}

private static void AddConfirmationData(Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityToken token)
{
var confirmationData = new Microsoft.IdentityModel.Tokens.Saml2.Saml2SubjectConfirmationData
{
Recipient = new Uri(_RequestACS),
NotOnOrAfter = DateTime.UtcNow.AddSeconds(tokenLifetime),
InResponseTo = new Microsoft.IdentityModel.Tokens.Saml2.Saml2Id(_RequestId),
};

token.Assertion.Subject.SubjectConfirmations.Add(new Microsoft.IdentityModel.Tokens.Saml2.Saml2SubjectConfirmation(
Microsoft.IdentityModel.Tokens.Saml2.Saml2Constants.ConfirmationMethods.Bearer, confirmationData));
}

private static void AddAuthenticationStatement(Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityToken token)
{
var authenticationMethod = "urn:oasis:names:tc:SAML:2.0:ac:classes:Password";
var authenticationContext = new Microsoft.IdentityModel.Tokens.Saml2.Saml2AuthenticationContext(new Uri(authenticationMethod));
var authenticationStatement = new Microsoft.IdentityModel.Tokens.Saml2.Saml2AuthenticationStatement(authenticationContext);
token.Assertion.Statements.Add(authenticationStatement);
}

private static string CreateSamlResponseXml(Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler tokenHandler, Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityToken token)
{
var buffer = new StringBuilder();

using (var stringWriter = new StringWriter(buffer))
using (var xmlWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings()))
{
xmlWriter.WriteStartElement("Response", "urn:oasis:names:tc:SAML:2.0:protocol");
xmlWriter.WriteAttributeString("IssueInstant", DateTime.UtcNow.ToString("o"));
xmlWriter.WriteAttributeString("ID", "_" + Guid.NewGuid());
xmlWriter.WriteAttributeString("Version", "2.0");

xmlWriter.WriteStartElement("Status");
xmlWriter.WriteStartElement("StatusCode");
xmlWriter.WriteAttributeString("Value", "urn:oasis:names:tc:SAML:2.0:status:Success");
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();

tokenHandler.WriteToken(xmlWriter, token);

xmlWriter.WriteEndElement();
}
return buffer.ToString();
}

private static Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor CreateTokenDescriptor(IEnumerable<Microsoft.IdentityModel.Claims.Claim> claims)
{
var descriptor = new Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor()
{
TokenType = Microsoft.IdentityModel.Tokens.SecurityTokenTypes.OasisWssSaml2TokenProfile11,
Lifetime = new Microsoft.IdentityModel.Protocols.WSTrust.Lifetime(DateTime.UtcNow, DateTime.UtcNow.AddMinutes(1)),
//AppliesToAddress = appliesTo,
AppliesToAddress = _RequestACS,
TokenIssuerName = issuer,
Subject = new Microsoft.IdentityModel.Claims.ClaimsIdentity(claims),
SigningCredentials = GetSigningCredentials()
};

return descriptor;
}

private static System.IdentityModel.Tokens.SigningCredentials GetSigningCredentials()
{
System.Security.Cryptography.X509Certificates.X509Certificate2 myCertificate = null;

X509Certificate2Collection selectedCerts = new X509Certificate2Collection();

X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);

foreach (System.Security.Cryptography.X509Certificates.X509Certificate2 cert in store.Certificates)
{
if (cert.SerialNumber.Trim().ToLower().Equals(CertificateSerialNumber.ToLower())){ myCertificate = cert; }
}
return new Microsoft.IdentityModel.SecurityTokenService.X509SigningCredentials(myCertificate, System.IdentityModel.Tokens.SecurityAlgorithms.RsaSha1Signature, System.IdentityModel.Tokens.SecurityAlgorithms.Sha1Digest);
}

private static IEnumerable<Microsoft.IdentityModel.Claims.Claim> CreateClaims()
{
foreach (var claimDescriptor in _claimDescriptors)
{
yield return new Microsoft.IdentityModel.Claims.Claim(claimDescriptor.Key, claimDescriptor.Value);
}
}

}

最佳答案

除了 SigningCredentials 属性之外,SecurityTokenDescriptor 和 Saml2SecurityToken 类还有一个 EncryptingCredentials 属性。设置它,断言将被加密。

签名响应可能更棘手。在获得带有加密断言的响应 xml 之后,您可以使用 SignedXml class为了这个目的。一个例子是 https://github.com/Safewhere/CHTestSigningService/blob/86a66950d1ffa5208b8bf80d03868a073ba29f12/Kombit.Samples.CHTestSigningService/Code/TokenSigningService.cs#L344

关于c# - 如何使用 C# 签署 SAMLResponse 和加密断言?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46529504/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com