Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ajax/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用C#对SAMLResponse进行签名和加密断言?_C#_.net_Authentication_Saml_Saml 2.0 - Fatal编程技术网

如何使用C#对SAMLResponse进行签名和加密断言?

如何使用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

我有一个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);
        }
    }

}
公共类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