我有:

  • 一个被动的STS“登录应用程序”也是身份提供商。
  • 可以接受和处理ACTAS代币的活动STS WCF服务
  • 网站依赖聚会
  • 网站调用的WCF服务依赖方。

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

我现在正在工作的是:

  1. 用户尝试访问网站RP。
  2. 用户被重定向到被动STS。
  3. 用户登录,发出令牌,将其重定向回到网站RP。
  4. 网站RP对WCF RP进行服务调用,并通过ACTAS代币,因此委派发生。
  5. Active STS看到ACTAS令牌进来并正确设置输出身份,因此主要身份是Actas令牌,呼叫者的身份添加到了演员链中。
  6. WCF RP拥有适当的所有设备,当前线程本金具有正确的身份和应有的索赔。

我希望WCF RP从Active STS请求其他索赔。

也就是说,在Active STS的第一个中,我希望它包括该服务所需的索赔列表,以便如果尚未出现这些额外的索赔。

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

我有一种感觉与我使用的绑定有关。我很难获得WS2007FEDERATIONHTPBINDING使用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>

如果我更改调用网站上的配置以指示发行的parkarameters部分中的索赔类型,那么Active STS实际上确实在第一个中看到了所需索赔的列表...但是,这在调用网站上,这对我来说是有问题的。

我如何做到这一点,以便WCF RP可以指定所需的其他索赔,而无需在调用网站上复制该配置?

如果确实是一个具有约束力的问题,那么如果您可以向我展示我上面的内容,那将有所帮助。我可以通过适当的更改更新网站和WCF服务,但是再次,我需要服务(或服务上的行为或服务上的配置)来控制所需的索赔列表。该服务不应接受缺少所需索赔的请求。

有帮助吗?

解决方案

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

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

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

无论如何,您可以看到一些体面的解释 WSTrustChannelFactoryWSTrustChannel 在MSDN网站上. 。我的解决方案是基于此的。

沸腾而没有所有错误处理等。代码基本上看起来像这样:

// 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堆栈为您处理。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top