WSTrustChannelFactory 和 WSTrustChannel

熟知 Windows Communication Foundation (WCF) 的人都知道 WCF 客户端已具备联合身份验证感知能力。 通过为 WCF 客户端配置 WSFederationHttpBinding 或类似自定义绑定,您可以启用针对服务的联合身份验证。

WCF 会在后台获取由安全令牌服务 (STS) 颁发的令牌,并使用此令牌向服务证明自己的身份。 这种方法的主要限制是看不到客户与服务器的通信。WCF 会根据绑定上的已颁发令牌参数自动生成要发送给 STS 的请求安全令牌 (RST)。 这表示客户端无法针对每个请求改变 RST 参数,无法检查请求安全令牌响应 (RSTR) 来获取显示声明等信息,也无法缓存令牌以备将来使用。

目前,WCF 客户端适合于基本的联合身份验证方案。 不过,Windows® Identity Foundation (WIF) 支持的一个主要方案需要在一个不能轻易被 WCF 允许的级别对 RST 进行控制。 因此,WIF 增加了一些功能,便于您对与 STS 之间的通信进行更多控制。

WIF 支持以下联合身份验证方案:

  1. 使用没有任何 WIF 依赖关系的 WCF 客户端向联合身份验证服务证明自己的身份

  2. 在 WCF 客户端上启用 WIF,以便将 ActAs 或 OnBehalfOf 元素插入 RST,然后发送至 STS

  3. 仅使用 WIF 从 STS 获取令牌,然后允许 WCF 客户端使用此令牌进行身份验证

第一个方案不言自明:现有的 WCF 客户端将继续使用 WIF 信赖方和 STS。 本主题讨论其余两个方案。

用 ActAs/OnBehalfOf 增强现有 WCF 客户端

在典型的标识委派方案中,客户端调用中间层服务,然后中间层服务调用后端服务。 中间层服务充当或代表客户端。 (有关详细信息,请参阅常见问题中的“ActAs 和 OnBehalfOf”一节。) 此信息是使用 RST 中的 ActAs 和 OnBehalfOf 令牌元素传达给 WS-Trust 颁发者的。

WCF 会公开绑定上的一个扩展点,以允许将任意 XML 元素添加到 RST 中。 不过,由于扩展点被约束在绑定上,所以如果方案要求 RST 内容随调用而改变,则必须针对每个调用重新创建客户端,而这会降低性能。WIF 会使用 ChannelFactory 类上的扩展方法,允许开发人员将在区外获取的任何令牌附加到 RST 中。 下面的代码示例说明如何获取代表客户端的令牌(如 X.509、用户名或安全声明标记语言 (SAML) 令牌)并将其附加到发给颁发者的 RST 中。

IHelloService serviceChannel = channelFactory.CreateChannelActingAs<IHelloService>( clientSamlToken ); serviceChannel.Hello(“Hi!”);

WIF 提供以下好处:

  • RST 可以按通道修改;因此,中间层服务不必针对每个客户端重新创建通道工厂,这样可提高性能。

  • 这适用于现有的 WCF 客户端,便于那些希望启用标识委派语义的现有 WCF 中间层服务找到便捷的升级路径。

不过,仍然看不到客户端与 STS 的通信。 我们将在第三个方案中对此进行检查。

直接与颁发者通信并使用所颁发的令牌进行身份验证

对于某些高级方案,增强 WCF 客户端是不够的。 仅使用 WCF 的开发人员通常使用 Message In/Message Out 协定并手动处理颁发者响应的客户端解析。

WIF 引入了 WSTrustChannelFactoryWSTrustChannel 类,让客户端直接与 WS-Trust 颁发者进行通信。 WSTrustChannelFactoryWSTrustChannel 类允许强类型 RST 和 RSTR 对象在客户端和颁发者之间流动,如下面的代码示例所示。

WSTrustChannelFactory trustChannelFactory = new WSTrustChannelFactory( stsBinding, stsAddress ); WSTrustChannel channel = (WSTrustChannel) trustChannelFactory.CreateChannel(); RequestSecurityToken rst = new RequestSecurityToken(RequestTypes.Issue); rst.AppliesTo = new EndpointAddress(serviceAddress); RequestSecurityTokenResponse rstr = null; SecurityToken token = channel.Issue(rst, out rstr);

请注意,Issue 方法上的 out 参数允许访问 RSTR 以进行客户端检查。

至此,我们仅了解到如何获取令牌。 从 WSTrustChannel 对象返回的令牌是 GenericXmlSecurityToken,其中包含向信赖方证明自己身份所必需的所有信息。 下面的代码示例说明如何使用此令牌。

IHelloService serviceChannel = channelFactory.CreateChannelWithIssuedToken<IHelloService>( token ); serviceChannel.Hello(“Hi!”);

ChannelFactory 对象上的 CreateChannelWithIssuedToken 扩展方法会让 WIF 知道您已在区外获取令牌,且它应该停止对颁发者的常规 WCF 调用,而改用您所获取的令牌向信赖方证明自己的身份。 这有以下好处:

  • 让您完全控制令牌颁发过程。

  • 通过直接在传出 RST 上设置 ActAs/OnBehalfOf 属性来支持 ActAs/OnBehalfOf 方案。

  • 允许根据 RSTR 的内容进行动态客户端信任决策。

  • 让您缓存并重复使用从 Issue 方法返回的令牌。

  • WSTrustChannelFactoryWSTrustChannel 允许根据 WCF 最佳实践对通道缓存、故障和恢复语义进行控制。

有关详细信息,请参阅 WIF 安装位置中的 Extensibility/WSTrustChannel 示例。