【问题标题】:Configuring Windows Identity Foundation from code从代码配置 Windows Identity Foundation
【发布时间】:2011-06-22 09:47:39
【问题描述】:

我正在试验“无配置 WIF”,我想接受由 Windows Azure 的 AppFabric STS 生成的 SAML2 令牌。

我正在做的是解析检查当前请求的令牌信息,如下所示:

        if (Request.Form.Get(WSFederationConstants.Parameters.Result) != null)
        {
            SignInResponseMessage message = 
                WSFederationMessage.CreateFromFormPost(System.Web.HttpContext.Current.Request) as SignInResponseMessage;

            var securityTokenHandlers = SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection();                    

            XmlTextReader xmlReader = new XmlTextReader(
                new StringReader(message.Result));

            SecurityToken token = securityTokenHandlers.ReadToken(xmlReader);

            if (token != null)
            {
                ClaimsIdentityCollection claims = securityTokenHandlers.ValidateToken(token);
                IPrincipal principal = new ClaimsPrincipal(claims);
            }
        }

上面的代码使用了 SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection();用于验证和处理 SAML 令牌的集合。但是:这不起作用,因为显然应用程序没有正确配置。如何在我的 securityTokenHandlers 集合上以编程方式从 XML 中指定以下配置?

  <microsoft.identityModel>
<service>
  <audienceUris>
    <add value="http://www.someapp.net/" />
  </audienceUris>
  <federatedAuthentication>
    <wsFederation passiveRedirectEnabled="true" issuer="https://rd-test.accesscontrol.appfabriclabs.com/v2/wsfederation" realm="http://www.thisapp.net" requireHttps="false" />
    <cookieHandler requireSsl="false" />
  </federatedAuthentication>
  <applicationService>
    <claimTypeRequired>
      <claimType type="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" optional="true" />
      <claimType type="http://schemas.microsoft.com/ws/2008/06/identity/claims/role" optional="true" />
    </claimTypeRequired>
  </applicationService>
  <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
    <trustedIssuers>
      <add thumbprint="XYZ123" name="https://somenamespace.accesscontrol.appfabriclabs.com/" />
    </trustedIssuers>
  </issuerNameRegistry>
</service>

【问题讨论】:

    标签: model-view-controller azure appfabric wif sts-securitytokenservice


    【解决方案1】:

    我也在苦苦挣扎,并在 WIF 3.5/4.0 中找到了可行的解决方案。由于 maartenba 的链接似乎已失效,因此我想在此处发布我的解决方案。

    我们的要求是:

    • 完全在代码中进行配置(因为我们随应用提供了默认的 web.config)
    • .Net 4.0 版允许的最大值(因此我使用的是 WIF 3.5/4.0)

    我曾经得出的解决方案:

    • Daniel Wu 提供的动态 WIF 配置信息 here。
    • This method 在运行时注册 HTTP 模块,由 David Ebbo 解释。一世 还尝试了更优雅的方法explained by Rick Strahl, 但不幸的是,这对我没有用。

    编辑 2016/09/02:而不是添加单独的“预应用程序启动 代码”类,如 David Ebbo 的示例,与 WIF 相关的 HTTP 模块 也可以在静态构造函数中注册 `HttpApplication' 类。我已经对代码进行了一些调整 更清洁的解决方案。

    我的解决方案在 web.config 中需要 nothing。大部分代码在 global.asax.cs 中。此示例中的配置是硬编码的:

    using System;
    using System.IdentityModel.Selectors;
    using System.Security.Cryptography.X509Certificates;
    using System.Web;
    using Microsoft.IdentityModel.Tokens;
    using Microsoft.IdentityModel.Web;
    
    namespace TestADFS
    {
      public class SessionAuthenticationModule : Microsoft.IdentityModel.Web.SessionAuthenticationModule
      {
        protected override void InitializePropertiesFromConfiguration(string serviceName)
        {
        }
      }
      public class WSFederationAuthenticationModule : Microsoft.IdentityModel.Web.WSFederationAuthenticationModule
      {
        protected override void InitializePropertiesFromConfiguration(string serviceName)
        {
          ServiceConfiguration = FederatedAuthentication.ServiceConfiguration;
          PassiveRedirectEnabled = true;
          RequireHttps = true;
          Issuer = "https://nl-joinadfstest.joinadfstest.local/adfs/ls/";
          Realm = "https://67px95j.decos.com/testadfs";
        }
      }
    
      public class Global : HttpApplication
      {
        static Global()
        {
          Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(SessionAuthenticationModule));
          Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(WSFederationAuthenticationModule));
        }
    
        protected void Application_Start(object sender, EventArgs e)
        {
          FederatedAuthentication.ServiceConfigurationCreated += FederatedAuthentication_ServiceConfigurationCreated;
        }
    
        internal void FederatedAuthentication_ServiceConfigurationCreated(object sender, Microsoft.IdentityModel.Web.Configuration.ServiceConfigurationCreatedEventArgs e)
        {
          X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
          store.Open(OpenFlags.ReadOnly);
          X509Certificate2Collection coll = store.Certificates.Find(X509FindType.FindByThumbprint, "245537E9BB2C086D3C880982FA86267FBD66B9A3", false);
          if (coll.Count > 0)
            e.ServiceConfiguration.ServiceCertificate = coll[0];
          store.Close();
          AudienceRestriction ar = new AudienceRestriction(AudienceUriMode.Always);
          ar.AllowedAudienceUris.Add(new Uri("https://67px95j.decos.com/testadfs"));
          e.ServiceConfiguration.AudienceRestriction = ar;
          ConfigurationBasedIssuerNameRegistry inr = new ConfigurationBasedIssuerNameRegistry();
          inr.AddTrustedIssuer("6C9B96D90257B65B6F181C2478D869473DC359EA", "http://NL-JOINADFSTEST.joinadfstest.local/adfs/services/trust");
          e.ServiceConfiguration.IssuerNameRegistry = inr;
          e.ServiceConfiguration.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None;
        }
    
        protected void Application_AuthenticateRequest(object sender, EventArgs e)
        {
          FederatedAuthentication.WSFederationAuthenticationModule.ServiceConfiguration = FederatedAuthentication.ServiceConfiguration;
        }
      }
    }
    

    用法

    我的应用是 asp.net WebForms,以经典管道模式运行,支持表单身份验证以及 ADFS 登录。因此,身份验证在所有 .aspx 页面共享的公共基类中处理:

        protected override void OnInit(EventArgs e)
        {
          if (NeedsAuthentication && !User.Identity.IsAuthenticated)
          {
            SignInRequestMessage sirm = new SignInRequestMessage(
              new Uri("https://nl-joinadfstest.joinadfstest.local/adfs/ls/"),
              ApplicationRootUrl)
            {
              Context = ApplicationRootUrl,
              HomeRealm = ApplicationRootUrl
            };
            Response.Redirect(sirm.WriteQueryString());
          }
          base.OnInit(e);
        }
    

    在此代码中,ApplicationRootUrl 是以“/”结尾的应用程序路径(“/”在经典管道模式下很重要)。

    由于混合模式下注销的稳定实现并不容易,我也想展示一下代码。从技术上讲,它可以工作,但在退出 ADFS 帐户后,我仍然遇到 IE 立即重新登录的问题:

          if (User.Identity.IsAuthenticated)
          {
            if (User.Identity.AuthenticationType == "Forms")
            {
              FormsAuthentication.SignOut();
              Session.Clear();
              Session.Abandon();
              ResetCookie(FormsAuthentication.FormsCookieName);
              ResetCookie("ASP.NET_SessionId");
              Response.Redirect(ApplicationRootUrl + "Default.aspx");
              HttpContext.Current.ApplicationInstance.CompleteRequest();
            }
            else
            {
              FederatedAuthentication.SessionAuthenticationModule.SignOut();
              FederatedAuthentication.SessionAuthenticationModule.DeleteSessionTokenCookie();
              Uri uri = new Uri(ApplicationRootUrl + "Default.aspx");
              WSFederationAuthenticationModule.FederatedSignOut(
                new Uri("https://nl-joinadfstest.joinadfstest.local/adfs/ls/"),
                uri); // 1st url is single logout service binding from adfs metadata
            }
          }
    

    (ResetCookie 是一个帮助函数,用于清除响应 cookie 并将其过期设置为过去)

    【讨论】:

    • IE 问题是由于 ADFS 被配置为专门针对该浏览器尝试 WIA 而不是基于 ADFS 表单的身份验证。 ADFS 服务器上的这个 PowerShell cmd 显示了执行此操作的浏览器:Get-AdfsProperties | select -ExpandProperty WIASupportedUserAgents 要为所有浏览器禁用 WIA,请将设置更改为仅非浏览器客户端:Set-AdfsProperties -WIASupportedUserAgents ("MSAuthHost/1.0/In-Domain","MSIPC","Windows Rights Management Client") 这解决了我的问题
    【解决方案2】:

    只是一个想法,不知道这是否可行:是否有办法获取实际的 XML(在您的情况下为空)并在运行时通过 Microsoft.IdentityModel.Configuration 中的类对其进行修改?

    或者,您可以在发送登录请求时修改 XML 中的某些内容,在 the RedirectingToIdentityProvider event 中通过修改 SignInRequestMessage

    【讨论】:

    • 不使用 WsFederationAuthenticationModule,其想法是不接触 Web.config 来注册模块或 IdentityModel 配置。将查看您提到的运行时配置更改,发现有关编写自定义 IssuerTokenValidators 等的其他一些问题。如果有任何解决办法,我会将其发布在 SO 上作为参考。
    【解决方案3】:

    仅供参考:找到解决方案并在此处描述(和链接)的模块中实现它:http://blog.maartenballiauw.be/post/2011/02/14/Authenticate-Orchard-users-with-AppFabric-Access-Control-Service.aspx

    【讨论】:

      猜你喜欢
      • 2011-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-10
      • 2012-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多