如何使用C#对SAMLResponse进行签名和加密断言?
我有一个IDP,它生成带有签名断言的SAMLResponse。我不打算添加生成的XML文件的示例,因为这会使问题变得太长。但如果这真的有帮助,请告诉我,我会补充 SP要求对断言进行加密并对响应进行签名,但目前情况并非如此。经过研究,我找不到怎么做,我会发布一些我尝试过的代码,但老实说,我有点不知所措,我尝试过的所有东西都一无所获 问题是,如何对响应签名并加密断言 以下是如何创建和签署响应:如何使用C#对SAMLResponse进行签名和加密断言?,c#,.net,authentication,saml,saml-2.0,C#,.net,Authentication,Saml,Saml 2.0,我有一个IDP,它生成带有签名断言的SAMLResponse。我不打算添加生成的XML文件的示例,因为这会使问题变得太长。但如果这真的有帮助,请告诉我,我会补充 SP要求对断言进行加密并对响应进行签名,但目前情况并非如此。经过研究,我找不到怎么做,我会发布一些我尝试过的代码,但老实说,我有点不知所措,我尝试过的所有东西都一无所获 问题是,如何对响应签名并加密断言 以下是如何创建和签署响应: public class SAML { private const int tokenLifeti
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);
}
}
}
公共类SAML
{
私有const int tokenlife=30;
私有常量字符串颁发者=”https://some.domain/IdP";
私有常量字符串证书SerialNumber=“xxxxxxxxxxxx”;
私有静态字符串_RequestId;
私有静态字符串_RequestIssueInstant;
私有静态字符串_RequestProviderName;
私有静态字符串_RequestACS;
私有静态字典_claimsdescriptors=新字典();
公共静态字符串CreateSamlResponse(字符串RequestId、字符串RequestIssueInstant、字符串RequestProviderName、字符串RequestACS、字典ClaimDescriptor)
{
_RequestId=RequestId;
_RequestIssueInstant=RequestIssueInstant;
_RequestProviderName=RequestProviderName;
_RequestACS=RequestACS;
_索赔描述符=索赔描述符;
var-claims=CreateClaims();
var tokenHandler=new Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler();
var-token=CreateToken(声明,tokenHandler);
返回CreateSamlResponseXml(令牌处理程序,令牌);
}
私有静态Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityToken CreateToken(IEnumerable声明,
Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler(标记处理程序)
{
var描述符=CreateTokenDescriptor(索赔);
var token=tokenHandler.CreateToken(描述符)为Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityToken;
AddAuthenticationStatement(令牌);
添加确认数据(令牌);
返回令牌;
}
私有静态void AddConfirmationData(Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityToken令牌)
{
var confirmationData=new Microsoft.IdentityModel.Tokens.Saml2.Saml2SubjectConfirmationData
{
收件人=新Uri(_RequestACS),
NOTONORFAFTER=DateTime.UtcNow.AddSeconds(令牌生存期),
InResponseTo=新的Microsoft.IdentityModel.Tokens.Saml2.Saml2Id(_RequestId),
};
token.Assertion.Subject.SubjectConfirmations.Add(新建Microsoft.IdentityModel.Tokens.Saml2.Saml2SubjectConfirmation(
Microsoft.IdentityModel.Tokens.Saml2.Saml2Constants.ConfirmationMethods.Bearer,confirmationData));
}
私有静态void AddAuthenticationStatement(Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityToken令牌)
{
var authenticationMethod=“urn:oasis:names:tc:SAML:2.0:ac:classes:Password”;
var authenticationContext=new Microsoft.IdentityModel.Tokens.Saml2.Saml2AuthenticationContext(新Uri(authenticationMethod));
var authenticationStatement=new Microsoft.IdentityModel.Tokens.Saml2.Saml2AuthenticationStatement(authenticationContext);
token.Assertion.Statements.Add(authenticationStatement);
}
私有静态字符串CreateSamlResponseXml(Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler tokenHandler,Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityToken tokenHandler)
{
var buffer=新的StringBuilder();
使用(var stringWriter=新的stringWriter(缓冲区))
使用(var xmlWriter=xmlWriter.Create(stringWriter,new XmlWriterSettings()))
{
writeStarteElement(“响应”,“urn:oasis:names:tc:SAML:2.0:protocol”);
WriteAttributeString(“IssueInstant”,DateTime.UtcNow.ToString(“o”);
xmlWriter.WriteAttributeString(“ID”、“”+Guid.NewGuid());
WriteAttributeString(“版本”,“2.0”);
xmlWriter.WriteStarteElement(“状态”);
writeStart元素(“状态代码”);
WriteAttributeString(“Value”,“urn:oasis:names:tc:SAML:2.0:status:Success”);
xmlWriter.WriteEndElement();
xmlWriter.WriteEndElement();
WriteToken(xmlWriter,令牌);
xmlWriter.WriteEndElement();
}
返回buffer.ToString();
}
私有静态Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor CreateTokenDescriptor(IEnumerable声明)
{
var descriptor=新的Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor()
{
TokenType=Microsoft.IdentityModel.Tokens.SecurityTokenTypes.OAISWSSSAML2TokenProfile11,
Lifetime=新的Microsoft.IdentityModel.Protocols.WSTrust.Lifetime(DateTime.UtcNow,DateTime.UtcNow.AddMinutes(1)),
//AppliesToAddress=appliesTo,
AppliesToAddress=\u RequestACS,
TokenIssuerName=issuer,
主题=新的Microsoft.IdentityModel.Claims.ClaimsEntity(索赔),
SigningCredentials=GetSigningCredentials()
};
返回描述符;
}
私有静态System.IdentityModel.Tokens.SigningCredentials GetSigningCredentials()
{
System.Security.Cryptography.X509Certificates.X509Certificate2 myCertificate=null;
X509Certificate2Collection selectedCerts=新X509Certificate2Collection();
X509Store=新的X509Store(StoreName.My,StoreLocation.LocalMachine);
打开(OpenFlags.ReadOnly);
foreach(System.Security.Cryptography.X509Certificates.X509Certificate2存储中的证书。证书)
{
如果(cert.SerialNumber.Trim().ToLower().Equals)(CertificateSerialNumber.ToLowe