3

我有:

  • 一个被动的 STS“登录应用程序”,它也是一个身份提供者。
  • 可以接受和处理 ActAs 令牌的活动 STS WCF 服务
  • 网站依赖方
  • 由网站调用的 WCF 服务依赖方。

所有这些都使用 Windows Identity Foundation 和自定义 STS 代码组合在一起。不涉及 Active Directory (ADFS)。

我现在的工作是:

  1. 用户尝试访问网站 RP。
  2. 用户被重定向到被动 STS。
  3. 用户登录,获得一个令牌,被重定向回网站 RP。
  4. 网站 RP 对 WCF RP 进行服务调用并传递一个 ActAs 令牌,以便进行委派。
  5. 活动 STS 看到 ActAs 令牌进入并正确设置输出身份,因此主要身份是 ActAs 令牌,调用者的身份被添加到 Actor 链中。
  6. WCF RP 在一切就绪的情况下获得正确的令牌,当前线程主体具有正确的身份和应有的声明。

我希望 WCF RP 向活动 STS 请求额外的声明。

也就是说,在进入活动 STS 的 RST 中,我希望它包含服务所需的声明列表,以便可以获取那些不存在的额外声明。

我已经通过修改网站 RP 客户端上的绑定来弄清楚如何做到这一点,但我希望在 WCF RP 服务端指定要求。

我觉得这与我正在使用的绑定有关。我在让 ws2007FederationHttpBinding 与 ActAs 令牌一起工作时遇到了麻烦,并且 WIF 身份培训工具包中的所有示例都使用了 customBinding,所以我也这样做了,它终于奏效了。这是来自 WCF RP 的配置片段,显示了我的绑定配置:

<system.serviceModel>
  <bindings>
    <customBinding>
      <binding name="CustomBinding_FederatedService">
        <security
          authenticationMode="IssuedTokenForCertificate"
          messageSecurityVersion="WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10">
          <issuedTokenParameters tokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1">
            <issuer address="http://localhost:38901/ActiveSts.svc/IWSTrust13" />
            <issuerMetadata address="http://localhost:38901/ActiveSts.svc/mex" />
          </issuedTokenParameters>
        </security>
        <textMessageEncoding>
          <readerQuotas maxArrayLength="32767" />
        </textMessageEncoding>
        <httpTransport />
      </binding>
    </customBinding>
  </bindings>
</system.serviceModel>

如果我更改调用网站上的配置以在issuedTokenParameters 部分中指示claimTypeRequirements,则Active STS 实际上确实会在RST 中看到所需声明的列表......但那是在调用网站上,这对我来说是有问题的。

如何使 WCF RP 可以指定它需要的其他声明,而不必在调用网站上复制该配置?

如果它确实是一个绑定问题,那么如果您可以根据我上面的内容向我展示等效配置,那将会有所帮助。我可以使用适当的更改来更新网站和 WCF 服务,但同样,我需要服务(或服务上的行为,或服务上的配置)来控制它需要的声明列表。该服务不应接受缺少所需声明的请求。

4

1 回答 1

4

事实证明,你必须这样做的方式是......

  1. 找出一种在客户端检索索赔要求的方法。这可能是某种中央配置服务、WS-Policy/元数据交换,或者任何你喜欢的东西。
  2. 为 STS 手动创建令牌请求。与其使用 Microsoft.IdentityModel 扩展方法,不如使用CreateChannelActingAs(token). 手动请求 ActAs 令牌(或新令牌)WSTrustChannelFactory
  3. 将手动请求的令牌添加到传出通道参数。

请注意,这并不能完全消除您的客户了解索赔要求列表的需要,但它确实使您能够以某种方式集中该配置,甚至使用服务本身来提供该索赔要求列表。不幸的是,Microsoft.IdentityModel 堆栈中没有任何东西可以为您完成所有这些工作。客户端绝对需要知道声明要求列表,因为对安全令牌的请求是作为客户端通信的一部分发出的,而不是在服务操作请求进入时由服务发出的。

无论如何,您可以在 MSDN 网站上看到一些不错的解释WSTrustChannelFactory和。我的解决方案就是基于此。WSTrustChannel

没有所有的错误处理等等,代码基本上是这样的:

// You need the channel factory so you can get info about the endpoint.
var factory = new ChannelFactory<IService>();

// Get the issuedTokenParameters information from the binding.
// You see this in the XML config but it's painful to access.
var tokenParameters = factory.Endpoint.Binding
    .CreateBindingElements()
    .OfType<SecurityBindingElement>().First()
    .EndpointSupportingTokenParameters
    .Endorsing.OfType<IssuedSecurityTokenParameters>().First();

// Prepare the RST.
var trustChannelFactory = new WSTrustChannelFactory(tokenParameters.IssuerBinding, tokenParameters.IssuerAddress);
var trustChannel = (WSTrustChannel)trustChannelFactory.CreateChannel();
var rst = new RequestSecurityToken(RequestTypes.Issue);
rst.AppliesTo = factory.Endpoint.Address;

// If you're doing delegation, set the ActAs value.
var principal = Thread.CurrentPrincipal as IClaimsPrincipal;
var bootstrapToken = principal.Identities[0].BootstrapToken;
rst.ActAs = new SecurityTokenElement(bootstrapToken);

// Here's where you can look up claims requirements dynamically.
rst.Claims.Add(new RequestClaim("http://dynamically-added-claim"));

// Get the token and attach it to the channel before making a request.
RequestSecurityTokenResponse rstr = null;
var issuedToken = trustChannel.Issue(rst, out rstr);
var fccParameters = new FederatedClientCredentialsParameters();
fccParameters.IssuedSecurityToken = issuedToken;
var channel = factory.CreateChannel();
((IChannel)channel).GetProperty<ChannelParameterCollection>().Add(fccParameters);

// NOW you can make the request.
channel.DoWork();

如果您希望优化系统周围的某些通信,这也允许您缓存已发布的令牌。

当然,如果您不尝试动态插入声明要求,或者如果您乐于使用 XML 配置并在服务器和客户端上复制它,则没有必要这样做。扩展方法和整个CreateChannelActingAs(token)Microsoft.IdentityModel 堆栈会为您解决这个问题。

于 2010-08-30T20:26:26.450 回答