5

我有一个 ASP.NET 应用程序,它使用 Azure ACS(以及间接的 ADFS)进行身份验证——一切正常。现在我被要求将 SessionToken 传递给另一个后端服务,在那里可以对其进行验证并提取声明。[长篇大论,不是我的选择]

我在解密方面很适合,我确定我缺少一些基本的东西。

为了设置阶段,解密时的错误是:

ID1006: The format of the data is incorrect. The encryption key length is negative: '-724221793'. The cookie may have been truncated.

ASP.NET 网站使用 RSA 包装器 ala:

    void WSFederationAuthenticationModule_OnServiceConfigurationCreated(object sender, ServiceConfigurationCreatedEventArgs e)
        {
            string thumbprint = "BDE74A3EB573297C7EE79EB980B0727D73987B0D";

            X509Certificate2 certificate = GetCertificate(thumbprint);

            List<CookieTransform> sessionTransforms = new List<CookieTransform>(new CookieTransform[] 
            { 
                new DeflateCookieTransform(), 
                new RsaEncryptionCookieTransform(certificate), 
                new RsaSignatureCookieTransform(certificate) 
            });

            SessionSecurityTokenHandler sessionHandler = new SessionSecurityTokenHandler(sessionTransforms.AsReadOnly());
            e.ServiceConfiguration.SecurityTokenHandlers.AddOrReplace(sessionHandler);
        }

(指纹与 FedUtil 在 web.config 中添加的值相同。

我用以下方式编写令牌:

    if (Microsoft.IdentityModel.Web.FederatedAuthentication.SessionAuthenticationModule.TryReadSessionTokenFromCookie(out token))
    {
        Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler th = new Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler();
        byte[] results = th.WriteToken(token);
    ...

这给了我:

    <?xml version="1.0" encoding="utf-8"?>
    <SecurityContextToken p1:Id="_53382b9e-8c4b-490e-bfd5-de2e8c0f25fe-94C8D2D9079647B013081356972DE275" 
                      xmlns:p1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" 
                      xmlns="http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512">
    <Identifier>urn:uuid:54bd1bd7-1110-462b-847e-7f49c1043b32</Identifier>
    <Instance>urn:uuid:0462b7d7-717e-4ce2-b942-b0d6a968355b</Instance>
    <Cookie xmlns="http://schemas.microsoft.com/ws/2006/05/security">AQAAANCMnd blah blah 1048 bytes total
    </Cookie>
    </SecurityContextToken>

并且,在另一个盒子上使用相同的证书(并且将令牌作为文件读入仅用于测试),我有:

    public static void Attempt2(FileStream fileIn, X509Certificate2 certificate, out SecurityToken theToken)
        {
            List<CookieTransform> sessionTransforms = new List<CookieTransform>(new CookieTransform[] 
            { 
                new DeflateCookieTransform(),
                new RsaSignatureCookieTransform(certificate), 
                new RsaEncryptionCookieTransform(certificate) 
            });

            SessionSecurityTokenHandler sessionHandler = new SessionSecurityTokenHandler(sessionTransforms.AsReadOnly());

            // setup
            SecurityTokenResolver resolver;
            {
                var token = new X509SecurityToken(certificate);

                var tokens = new List<SecurityToken>() { token };

                resolver = SecurityTokenResolver.CreateDefaultSecurityTokenResolver(tokens.AsReadOnly(), false);
            }

            sessionHandler.Configuration = new SecurityTokenHandlerConfiguration();
            sessionHandler.Configuration.IssuerTokenResolver = resolver;

            using (var reader = XmlReader.Create(fileIn))
            {
                theToken = sessionHandler.ReadToken(reader);
            }

        }

然后 ReadToken 抛出 FormatException

ID1006: The format of the data is incorrect. The encryption key length is negative: '-724221793'. The cookie may have been truncated.

在这一点上,我无法判断我的整体方法是否存在缺陷,或者我是否只是错过了解决所有这些问题的众所周知的“一条线”。

哦,我在网站上使用 VS2010 SP1 (.NET 4.0),我在解码端尝试了 VS2010SP1 .NET 4.0 和 VS2012 .NET 4.5。

谢谢!

4

2 回答 2

0

您的后端服务的应用程序池帐户是否具有对证书的读取权限?如果没有为后端服务授予您的应用程序池帐户对证书的读取权限。因此,我过去在加密/解密方面遇到了问题。

于 2013-05-22T01:57:34.357 回答
0

这可能会有所帮助,这会将您的 FedAuth cookie 转换为可读的 XML 字符串,例如:

    <?xml version="1.0" encoding="utf-8"?>
    <SecurityContextToken p1:Id="_548a372e-1111-4df8-b610-1f9f618a5687-953155F0C35B4862A5BCE4D5D0C5ADF0" xmlns:p1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns="http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512">
        <Identifier>urn:uuid:c9f9b733-1111-4b01-8af3-23c8af3e19a6</Identifier>
        <Instance>urn:uuid:ee955207-1111-4498-afa3-4b184e97d0be</Instance>
        <Cookie xmlns="http://schemas.microsoft.com/ws/2006/05/security">long_string==</Cookie>
    </SecurityContextToken>

代码:

    private string FedAuthToXmlString(string fedAuthCombinedString)
    {
        // fedAuthCombinedString is from FedAuth + FedAuth1 cookies: just combine the strings
    
        byte[] authBytes = Convert.FromBase64String(fedAuthCombinedString);
        string decodedString = Encoding.UTF8.GetString(authBytes);
    
        var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
        store.Open(OpenFlags.ReadOnly);
        var thumbprint = "CERT_THUMBPRINT";  // from config
    
        var cert = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false)[0];
    
        var sessionTransforms = new List<System.IdentityModel.CookieTransform>(new System.IdentityModel.CookieTransform[]
        {
            new System.IdentityModel.DeflateCookieTransform(),
            new System.IdentityModel.RsaSignatureCookieTransform(cert),
            new System.IdentityModel.RsaEncryptionCookieTransform(cert)
        });
    
        SessionSecurityTokenHandler sessionHandler = new SessionSecurityTokenHandler(sessionTransforms.AsReadOnly());
    
        SecurityTokenResolver resolver;
        {
            var token = new X509SecurityToken(cert);
            var tokens = new List<SecurityToken>() { token };
            resolver = SecurityTokenResolver.CreateDefaultSecurityTokenResolver(tokens.AsReadOnly(), false);
        }
    
        sessionHandler.Configuration = new SecurityTokenHandlerConfiguration();
        sessionHandler.Configuration.IssuerTokenResolver = resolver;
                
        var i = 0; // clear out invalid leading xml
        while ((int)decodedString[i] != 60 && i < decodedString.Length - 1) i++; // while the first character is not <

        store.Close();

        return decodedString.Substring(i);
    }
于 2017-06-29T18:58:08.663 回答