代码之家  ›  专栏  ›  技术社区  ›  Travis Illig

如何在服务端指定索赔类型要求,以便客户机请求遵守这些要求?

  •  3
  • Travis Illig  · 技术社区  · 14 年前

    我有:

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

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

    我现在的工作是:

    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>
    

    如果我更改调用网站上的配置以在IssuedTokeParameters部分指示ClaimTypeRequirements,那么活动的STS实际上会在RST中看到所需索赔的列表…但那是在主叫网站上,这对我来说是个问题。

    我如何才能使wcf rp可以指定它所需的其他声明,而不必在调用的网站上复制该配置?

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

    1 回复  |  直到 14 年前
        1
  •  4
  •   Travis Illig    14 年前

    结果你要做的就是…

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

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

    不管怎样,你可以看到一些关于 WSTrustChannelFactory(WSTrustChannelFactory) WSTrustChannel on the MSDN web site . 我的解决方案就是基于这个。

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

    // 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(令牌) 扩展方法和整个Microsoft.IdentityModel堆栈将为您处理此问题。