Windows Identity Foundation (WIF) 包括通过 WS-联合身份验证模块 (WS-FAM) 对 ASP.NET 应用程序中联合身份验证的支持。 本主题有助于理解联合身份验证的工作原理和使用方法。
联合身份验证概述
当两个信任域之间存在信任关系时,联合身份验证允许一个信任域中的安全令牌服务 (STS) 向另一个信任域中的 STS 提供身份验证信息。 出现这种是在下图中所示:
- Fabrikam 信任域中的客户端向 Contoso 信任域中的信赖方 (RP) 应用发送请求。
- RP 将客户端重定向到 Contoso 信任域中的 STS。 此 STS 完全不了解该客户端。
- Contoso STS 将该客户端重定向到 Fabrikam 信任域中的 STS,此信任域与 Contoso 信任域之间存在信任关系。
- Fabrikam STS 验证客户端的标识,并向 Contoso STS 颁发安全令牌。
- Contoso STS 使用 Fabrikam 令牌来创建自己的令牌(可由 RP 使用)并将其发送到 RP。
- RP 从安全令牌中提取客户端声明并做出授权决策。
将联合身份验证模块与 ASP.NET 搭配使用
WSFederationAuthenticationModule (WS-FAM) 是一个 HTTP 模块,可让你将联合身份验证添加到 ASP.NET 应用程序。 联合身份验证将身份验证逻辑交由 STS 处理,让你可以集中注意力编写业务逻辑。
可以配置 WS-FAM 来指定未经身份验证的请求应重定向到的 STS。 使用 WIF,可采用两种方式对用户进行身份验证:
- 被动重定向:当未经身份验证的用户尝试访问受保护的资源,并且想要将它们重定向到 STS 而无需登录页时,这是正确的方法。STS 验证用户标识,并颁发包含适合该用户的声明的安全令牌。 此选项需要将 WS-FAM 添加到 HTTP 模块管道。 可以使用用于 Visual Studio 2012 的标识和访问工具修改应用程序配置文件,以便使用 WS FAM 以及与 STS 联合。 有关详细信息,请参阅用于 Visual Studio 2012 的标识和访问工具。
- 对于信赖方应用程序中的登录页,可以从代码隐藏调用 WSFederationAuthenticationModule.SignIn 方法或 RedirectToIdentityProvider 方法。
在被动重定向中,所有通信通过来自客户端(通常为浏览器)的响应/重定向执行。 可将 WS-FAM 添加到应用程序的 HTTP 管道,它将在管道中监视未经身份验证的用户请求并将用户重定向到指定的 STS。
WS-FAM 也会引发几个可自定义其功能在 ASP.NET 应用程序中的事件。
WS-FAM 的工作原理
WS-FAM 在 WSFederationAuthenticationModule 类中实现。 通常情况下,将 WS-FAM 添加到你的 ASP.NET 信赖方应用程序的 HTTP 管道。 未经身份验证的用户尝试访问受保护资源时,RP 将返回 HTTP 响应“401 拒绝授权”。 WS-FAM 截获此响应,而不是让客户端接收它,然后将用户重定向到指定的 STS。 STS 颁发安全令牌,WS-FAM 再次将其截获。 WS-FAM 使用该令牌创建的实例ClaimsPrincipal身份验证的用户,这使正则.NET Framework 授权机制得以运行。
因为 HTTP 无状态,所以需要一种方法来避免在每次用户尝试访问另一个受保护资源时重复上述过程。 这时 SessionAuthenticationModule 便可派上用场。 当 STS 向用户颁发安全令牌时,SessionAuthenticationModule 也会为该用户创建会话安全令牌并将其放置于 Cookie 中。 在后续请求中,SessionAuthenticationModule 将截获此 Cookie 并使用它来重新构造用户的 ClaimsPrincipal。
下方的关系图展示了被动重定向事例中整体信息流。 通过 STS 自动重定向请求,无需登录页便可建立凭据:
下方的关系图展示了用户经过身份验证访问 STS 且由 WSFederationAuthenticationModule 处理其安全令牌后的更多详细信息:
下方的关系图展示了将用户的安全令牌串行化成 Cookie 并由 SessionAuthenticationModule 截获后的更多详细信息:
事件
WSFederationAuthenticationModule、SessionAuthenticationModule 和它们的父类 HttpModuleBase 在处理 HTTP 请求的各个阶段引发事件。 你可以处理这些事件中的global.asax
ASP.NET 应用程序文件。
- ASP.NET 基础结构调用模块的 Init 方法来初始化模块。
- ASP.NET 基础结构首次在派生于 HttpModuleBase 的某个应用程序模块上调用 Init 方法时将引发 FederatedAuthentication.FederationConfigurationCreated 事件。 此方法访问静态 FederatedAuthentication.FederationConfiguration 属性,导致从 Web.config 文件加载配置。 仅在首次访问此属性时引发该事件。 可以通过事件处理程序中的 FederationConfigurationCreatedEventArgs.FederationConfiguration 属性访问从配置中初始化的 FederationConfiguration 对象。 可以在将配置应用到任何模块前使用此事件修改配置。 可以在 Application_Start 方法中为此事件添加处理程序:
复制
void Application_Start(object sender, EventArgs e)
{
FederatedAuthentication.FederationConfigurationCreated += new EventHandler<FederationConfigurationCreatedEventArgs>(FederatedAuthentication_FederationConfigurationCreated);
}
每个模块替代 HttpModuleBase.InitializeModule 和 HttpModuleBase.InitializePropertiesFromConfiguration 抽象方法。 第一种方法为与模块相关的 ASP.NET 管道事件添加处理程序。 大多数情况下,模块的默认实现便已足够。 第二种方法从模块的 HttpModuleBase.FederationConfiguration 属性初始化其各个属性。 (这是之前加载的配置的副本。)如果要支持从派生自 WSFederationAuthenticationModule 或 SessionAuthenticationModule 的类中的配置初始化新属性,则需要替代第二种方法。 在此情况下,也需要从相应的配置对象进行派生,从而支持添加的配置属性;例如,从 IdentityConfiguration、WsFederationConfiguration 或 FederationConfiguration 派生。
- WS-FAM 截获由 STS 颁发的安全令牌时引发 SecurityTokenReceived 事件。
- WS-FAM 在验证令牌后引发 SecurityTokenValidated 事件。
- SessionAuthenticationModule 在为用户创建会话安全令牌时,引发 SessionSecurityTokenCreated 事件。
- SessionAuthenticationModule 使用包含会话安全令牌的 Cookie 截获后续请求时,引发 SessionSecurityTokenReceived 事件。
- 在 WS-FAM 将用户重定向到颁发者之前引发 RedirectingToIdentityProvider 事件。 事件中传递的 RedirectingToIdentityProviderEventArgs 的 SignInRequestMessage 属性提供 WS 联合身份验证登录请求。 可选择在将请求发送到颁发者之前修改请求。
- 成功写入 Cookie 且用户登录后,WS-FAM 引发 SignedIn 事件。
- 为每个用户关闭会话时,WS FAM 将对每个会话引发一次 SigningOut 事件。 如果在客户端上关闭会话(例如,通过删除会话 Cookie 的方式),则不会引发该事件。 在 SSO 环境中,IP-STS 也可以请求每个 RP 注销。 这也将引发此事件,这时 IsIPInitiated设置为
true
。
备注
不应在由 WSFederationAuthenticationModule 或 SessionAuthenticationModule 引发的任何事件期间使用 Thread.CurrentPrincipal 属性。 这是因为 Thread.CurrentPrincipal 是在身份验证进程后设置的,而事件是在身份验证进程中引发的。
联合身份验证的配置
WS-FAM 和 SAM 通过 元素进行配置。 子元素配置 WS-FAM 属性的默认值;例如 Issuer属性和 Realm 属性。 (可以通过为一些 WS-FAM 事件提供处理程序来按请求更改这些值;例如 RedirectingToIdentityProvider。)由 SAM 使用的 Cookie 处理程序通过 子元素进行配置。 WIF 提供在 ChunkedCookieHandler 类中实现的默认 Cookie 处理程序,可以通过 元素设置该处理程序的区块大小。 <federationConfiguration>
元素引用 IdentityConfiguration,为在应用程序中使用的其他 WIF 组件提供配置,如 ClaimsAuthenticationManager 和 ClaimsAuthorizationManager。 可以通过指定 <federationConfiguration>
元素的 identityConfigurationName
属性中名为 的元素显式引用标识配置。 如果未显式引用标识配置,则将使用默认标识配置。
以下 XML 演示 ASP.NET 信赖方 (RP) 应用的配置。 SystemIdentityModelSection 和 SystemIdentityModelServicesSection 配置部分添加在 <configSections>
元素之下。 SAM 和 WS-FAM 添加到 <system.webServer>
/<modules>
元素下的 HTTP 模块。 最后,WIF 组件在 <system.identityModel>
/<identityConfiguration>
和 <system.identityModel.services>
/<federationConfiguration>
元素下进行配置。 此配置指定分块 Cookie 处理程序(因为它是默认 Cookie 处理程序),且 <cookieHandler>
元素中没有指定的 Cookie 处理程序类型。
警告
在以下示例中,<wsFederation>
元素的 requireHttps
属性和 <cookieHandler>
元素的 requireSsl
属性皆为 false
。 这表示潜在的安全威胁。 在生产中,这两个值都应设置为 true
。
XML复制
<configuration>
<configSections>
<section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
<section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
</configSections>
...
<system.webServer>
<modules>
<add name="WSFederationAuthenticationModule" type="System.IdentityModel.Services.WSFederationAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
<add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
</modules>
</system.webServer>
<system.identityModel>
<identityConfiguration>
<audienceUris>
<add value="http://localhost:50969/" />
</audienceUris>
<certificateValidation certificateValidationMode="None" />
<issuerNameRegistry type="System.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<trustedIssuers>
<add thumbprint="9B74CB2F320F7AAFC156E1252270B1DC01EF40D0" name="LocalSTS" />
</trustedIssuers>
</issuerNameRegistry>
</identityConfiguration>
</system.identityModel>
<system.identityModel.services>
<federationConfiguration>
<wsFederation passiveRedirectEnabled="true" issuer="http://localhost:15839/wsFederationSTS/Issue" realm="http://localhost:50969/" reply="http://localhost:50969/" requireHttps="false" />
<cookieHandler requireSsl="false" />
</federationConfiguration>
</system.identityModel.services>
</configuration>