Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/35.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读入SecurityToken对象时遇到问题_C#_Asp.net_.net_Asp.net Mvc_Single Sign On - Fatal编程技术网

C# 将此SAMLResponse读入SecurityToken对象时遇到问题

C# 将此SAMLResponse读入SecurityToken对象时遇到问题,c#,asp.net,.net,asp.net-mvc,single-sign-on,C#,Asp.net,.net,Asp.net Mvc,Single Sign On,我正在运行一个SSO登录页面,当我成功地对自己进行身份验证时,该页面使用SAMLResponse字符串进行POST,该字符串包含对我的.NET MVC应用程序的base-64编码SAML响应。如果可能,我正在尝试将其解析为对象: var tokenString = Encoding.UTF8.GetString(Convert.FromBase64String(base64EncodedSamlToken)); var token = System.IdentityModel.Services.

我正在运行一个SSO登录页面,当我成功地对自己进行身份验证时,该页面使用SAMLResponse字符串进行POST,该字符串包含对我的.NET MVC应用程序的base-64编码SAML响应。如果可能,我正在尝试将其解析为对象:

var tokenString = Encoding.UTF8.GetString(Convert.FromBase64String(base64EncodedSamlToken));
var token = System.IdentityModel.Services.FederatedAuthentication.FederationConfiguration.IdentityConfiguration.SecurityTokenHandlers.ReadToken(new XmlTextReader(new StringReader(tokenString)));
token
的值始终为空,因此无法正确解析,但这是为什么

在令牌的XML中,我看到了其他XML标记和数据,其中包括以下响应标记:

<saml2p:Response Destination="https://blah.local/" ID="_be8cc118c528ba0407446b8cc2dca019" InResponseTo="ID-302e3473-f063-43b0-b8e4-b8f47fbbe350" IssueInstant="2015-12-29T16:19:35.603Z" Version="2.0" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">https://shibboleth.blah.local/idp/shibboleth</saml2:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">

如何从这个相同的响应中获取SecurityToken?

我找到了一个解决方案。一旦我将SAMLResponse作为字符串抓取,我就可以对其进行反序列化,但反序列化的方法非常细致,因为编码是在构建令牌时导致Saml2SecurityToken构造函数失败的可靠方法(这肯定是个坏东西)

想法很简单,从XML中获取
saml2:Assertion
标记作为元素,并使用它构建
SecurityToken
;它在我的情况下经过测试并能正常工作,因此希望它能帮助其他人:

var samlToken = (SecurityToken)null;
var form = await Request.ReadFormAsync(); // I am using IOwinRequest here, but if you are using something else you can probably fetch this parameter from somewhere within HttpContext.Current.Request.Form["SAMLResponse"]; or elsewhere.
if (form.Count() > 0)
{
    var samlResponses = form.GetValues("SAMLResponse");
    if (samlResponses != null && samlResponses.Count > 0)
    {
        foreach (var samlResponse in samlResponses)
        {
            try
            {
                var decodedSamlResponse = Convert.FromBase64String(samlResponse);
                var reader = XmlReader.Create(new MemoryStream(decodedSamlResponse));
                var serializer = new XmlSerializer(typeof(XmlElement));
                var samlResponseElement = (XmlElement)serializer.Deserialize(reader);
                var manager = new XmlNamespaceManager(samlResponseElement.OwnerDocument.NameTable);
                manager.AddNamespace("saml2", "urn:oasis:names:tc:SAML:2.0:assertion");
                var assertion = (XmlElement)samlResponseElement.SelectSingleNode("//saml2:Assertion", manager);
                samlToken = (Saml2SecurityToken)Options.SecurityTokenHandlers.ReadToken(XmlReader.Create(new StringReader(assertion.OuterXml)));
                break;
            }
            catch { }
        }
    }
}

你说得对。WIF仍然支持SAML2p。有一些实现确实支持它,即ADFS或Azure AD支持SAML2p作为IDP。你可以试试,这太奇怪了,他们从来没有把它集成到WIF中。这是最受欢迎的功能之一,因此听到这一点我完全感到困惑。@pepo一旦你找到了正确反序列化断言的方法,它最终并没有那么糟糕。最大的问题是找到那个把戏。很高兴听到(读到:)@pepo我也是:)一切顺利时都很好
var samlToken = (SecurityToken)null;
var form = await Request.ReadFormAsync(); // I am using IOwinRequest here, but if you are using something else you can probably fetch this parameter from somewhere within HttpContext.Current.Request.Form["SAMLResponse"]; or elsewhere.
if (form.Count() > 0)
{
    var samlResponses = form.GetValues("SAMLResponse");
    if (samlResponses != null && samlResponses.Count > 0)
    {
        foreach (var samlResponse in samlResponses)
        {
            try
            {
                var decodedSamlResponse = Convert.FromBase64String(samlResponse);
                var reader = XmlReader.Create(new MemoryStream(decodedSamlResponse));
                var serializer = new XmlSerializer(typeof(XmlElement));
                var samlResponseElement = (XmlElement)serializer.Deserialize(reader);
                var manager = new XmlNamespaceManager(samlResponseElement.OwnerDocument.NameTable);
                manager.AddNamespace("saml2", "urn:oasis:names:tc:SAML:2.0:assertion");
                var assertion = (XmlElement)samlResponseElement.SelectSingleNode("//saml2:Assertion", manager);
                samlToken = (Saml2SecurityToken)Options.SecurityTokenHandlers.ReadToken(XmlReader.Create(new StringReader(assertion.OuterXml)));
                break;
            }
            catch { }
        }
    }
}