如何将 SAML XML 令牌字符串转换为 SecurityToken 或 ClaimsPrincipal 实例?

Posted

技术标签:

【中文标题】如何将 SAML XML 令牌字符串转换为 SecurityToken 或 ClaimsPrincipal 实例?【英文标题】:How to convert SAML XML token string to either SecurityToken or ClaimsPrincipal instance? 【发布时间】:2011-02-03 11:10:34 【问题描述】:

我的背景:

.Net RESTful Web 服务 客户端(混合平台、技术、库功能)已获得 SAML 令牌 尝试接受令牌以在 REST 服务中进行身份验证/授权 在 HTTP 授权/X-Authorization 标头中 作为查询参数 稍后也会支持 SWT,但需要让 SAML 令牌运行

详情:

我在字符串中有一个 SAML 令牌:

<saml:Assertion xmlns:saml="..." ...> ..etc... </>

在 HttpModule 中,我想将其转换为 ClaimsPrincipal 以便我的服务可以像 IClaimsPrincipal 一样执行通常的 Thread.CurrentPrincipal。

我发现了一些看起来很有帮助的诱人页面/博客/等:

Cibrax's Idea for passing the token in the HTTP Authorization header Dominick Baier on something similar for SWT, with mention of easily doing same for SAML

我一直在试图将 SAML 令牌转换为 ClaimsPrincipal(通过 SecurityToken 中间步骤或直接......无论哪种方式都很高兴)。 Cibrax 想法的示例代码使用以下关键验证和反序列化步骤:

SecurityTokenSerializer securityTokenSerializer 
    = new SecurityTokenSerializerAdapter(
        FederatedAuthentication.SecurityTokenHandlers, 
        MessageSecurityVersion.Default.SecurityVersion, 
        false, new SamlSerializer(), null, null);

SecurityToken theToken 
    = WSFederationAuthenticationModule.GetSecurityToken(
        theSamlTokenInStringForm, securityTokenSerializer);

我遇到的障碍是 WIF 的 RTM 版本没有公开 GetSecurityToken 的这种重载......它只公开:

WSFederationAuthenticationModule fam = new WSFederationAuthenticationModule();
SecurityToken theToken = fam.GetSecurityToken(HttpRequest theRequest);
SecurityToken theToken = fam.GetSecurityToken(SignInResponseMessage message);

感谢您帮助我摆脱困境!

泰勒

【问题讨论】:

我正在寻找可以处理加密 SWT 和 SAML 令牌的类似解决方案。我最感兴趣的是获得一个不会修改我现有会话凭据的安全令牌。 你得到最终解决方案了吗?未标记答案... @LamonteCristo 类似的解决方案? 【参考方案1】:

刚刚发现这很有帮助。 http://www.tecsupra.com/blog/system-identitymodel-manually-parsing-the-saml-token/

基本思路:你需要“Audience”节点的XML,然后你可以使用SecurityTokenHandlerCollection和使用“ValidateToken”

来自帖子:

       string samlTokenXml = signInResponseXml
            .DocumentElement  // <trust:RequestSecurityTokenResponseCollection>
            .ChildNodes[0] // <trust:RequestSecurityTokenResponse>
            .ChildNodes[2] // <trust:RequestedSecurityToken>
            .InnerXml; // <Assertion>

        var xmlTextReader = new XmlTextReader(new StringReader(samlTokenXml));

        SecurityTokenHandlerCollection handlers = 
       FederatedAuthentication.FederationConfiguration.IdentityConfiguration.SecurityTokenHandlers;

        // read the token
        SecurityToken securityToken = handlers.ReadToken(xmlTextReader);

【讨论】:

我认为你的意思是“Assertion”而不是“Audience”和“ReadToken”而不是“ValidateToken”,但这篇文章相当不错+1 刚刚检查了我的解决方案:起初我通过“ReadToken”读取SecurityToken并通过“ValidateToken”验证它(代码sn-p中不存在,但需要) - 所以你是正确。【参考方案2】:

我想分享一些我发现在实现基本相同的场景时非常有用的资源。基本上,Dominick Baier 是这个领域的神。他的博客充满了关于这个主题的重要信息:

http://leastprivilege.com/

在 RESTful 服务中将 SAML/SWT 令牌转换为 IClaimsIdentity:

http://www.develop.com/wcfrest/

http://identitymodel.codeplex.com/

【讨论】:

【参考方案3】:

要解决最后一个异常,请检查标签及其内容并确保其正确。我不能说哪个元素有问题。我们有时会出现这个错误,每次的原因是身份模型部分格式错误。

【讨论】:

【参考方案4】:

好的,有些进展...如果我执行以下操作,我会更进一步:

Microsoft.IdentityModel.Configuration.ServiceConfiguration serviceConfig
    = new Microsoft.IdentityModel.Configuration.ServiceConfiguration();

// Now read the token and convert it to an IPrincipal
SecurityToken theToken = null;
ClaimsIdentityCollection claimsIdentity = null;
using (XmlReader reader = XmlReader.Create(new StringReader(authSamlString)))

    theToken = serviceConfig.SecurityTokenHandlers.ReadToken(reader);
    claimsIdentity = serviceConfig.SecurityTokenHandlers.ValidateToken(theToken);


IPrincipal principal = new ClaimsPrincipal(claimsIdentity);

我撞到的下一堵墙:

我现在在向导生成的 REST 服务主机分配中遇到异常:

<%@ ServiceHost Language="C#" Debug="true" Service="Sample.RestService.Service" Factory="Sample.RestService.AppServiceHostFactory"%>

using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
using Microsoft.ServiceModel.Web.SpecializedServices;

namespace Sample.RestService 

  class AppServiceHostFactory : ServiceHostFactory
  
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    
        /// ***** The exception occurs on the next line *****
        return new SingletonServiceHost(serviceType, baseAddresses);
    
  

异常详情:

System.Configuration.ConfigurationErrorsException occurred
  Message="This element is not currently associated with any context"
  Source="System.Configuration"
  BareMessage="This element is not currently associated with any context"
  Line=0
  StackTrace:
       at System.Configuration.ConfigurationElement.get_EvaluationContext()
  InnerException: NONE

【讨论】:

这是在哪个版本的 .Net 上?如果少于 4 个,请参阅 ***.com/questions/1189331/… 以获得对您所看到内容的可能解释!

以上是关于如何将 SAML XML 令牌字符串转换为 SecurityToken 或 ClaimsPrincipal 实例?的主要内容,如果未能解决你的问题,请参考以下文章

将 java webapp 转换为使用 SAML2 身份验证

如何将设备令牌(NSData)转换为NSString?

将时间字符串 (Hour:Min:Sec.Millsecs) 快速转换为浮点数

将时间字符串 (Hour:Min:Sec.Millsecs) 快速转换为浮点数

如何使用 C# 正确准备“HTTP 重定向绑定”SAML 请求

为已通过身份验证的用户向 SP 发起 SAML 2.0 发布