4

我有一个 WinForms 应用程序,其中包含从使用 WS2007FederationHttpBinding 的 WCF 服务生成的服务参考。我不明白为什么以下不起作用。

我的 WinForms 应用程序正在调用使用 Thinktecture.IdentityServer 的 WCF 服务,该服务设置为处理 BearerKey 类型令牌。

从我的客户那里,我只需获取一个有效的访问令牌,然后进行以下调用:

    private static void CallServiceReference(SecurityToken token)
    {
        ServiceReference1.ClaimsServiceContractClient svcRef = new ServiceReference1.ClaimsServiceContractClient();

        svcRef.ChannelFactory.Credentials.SupportInteractive = false;
        svcRef.ChannelFactory.CreateChannelWithIssuedToken(token);
        var claims = svcRef.GetClaims(); 
    }

以下是服务参考的 winforms 客户端 app.config:

<system.serviceModel>
      <bindings>
              <ws2007FederationHttpBinding>
                      <binding name="WS2007FederationHttpBinding_ClaimsServiceContract">
                              <security mode="TransportWithMessageCredential">
                                      <message establishSecurityContext="false" issuedKeyType="BearerKey">
                                              <issuer address="https://identity.MyCo.com/issue/wsfed" binding="ws2007HttpBinding"
                                                      bindingConfiguration="https://identity.MyCo.com/issue/wstrust/mixed/username" />
                                              <issuerMetadata address="https://identity.MyCo.com/issue/wstrust/mex" />
                                              <tokenRequestParameters>
                                                      <trust:SecondaryParameters xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">
                                                              <trust:KeyType xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://docs.oasis-open.org/ws-sx/ws-trust/200512/Bearer</trust:KeyType>
                                                              <trust:CanonicalizationAlgorithm xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2001/10/xml-exc-c14n#</trust:CanonicalizationAlgorithm>
                                                              <trust:EncryptionAlgorithm xmlns:trust="http://docs.oasis-open.org/ws-sx/ws-trust/200512">http://www.w3.org/2001/04/xmlenc#aes256-cbc</trust:EncryptionAlgorithm>
                                                      </trust:SecondaryParameters>
                                              </tokenRequestParameters>
                                      </message>
                              </security>
                      </binding>
              </ws2007FederationHttpBinding>
              <ws2007HttpBinding>
                      <binding name="https://identity.MyCo.com/issue/wstrust/mixed/username">
                              <security mode="TransportWithMessageCredential">
                                      <transport clientCredentialType="None" />
                                      <message clientCredentialType="IssuedToken" establishSecurityContext="false" />
                              </security>
                      </binding>
              </ws2007HttpBinding>
      </bindings>
      <client>
              <endpoint address="https://roadie/WebTest/service.svc" binding="ws2007FederationHttpBinding"
                      bindingConfiguration="WS2007FederationHttpBinding_ClaimsServiceContract"
                      contract="ServiceReference1.ClaimsServiceContract" name="WS2007FederationHttpBinding_ClaimsServiceContract" />
      </client>
  </system.serviceModel>

当我尝试执行服务调用 (svcRef.GetClaims()) 时,我收到此错误:

“未指定安全令牌颁发者的地址。必须在目标' https://identity.MyCo.com/issue/wsfed '的绑定中指定明确的颁发者地址,或者必须在凭据中配置本地颁发者地址。”

这个错误很蹩脚,而且令人困惑,似乎在配置中指定了一个发行者!

最后,我知道 WCF 服务和身份服务是有效的,因为这一切都可以使用自定义 ChannelFactory 正常工作,也使用完全相同的方法来应用令牌:

var channel = factory.CreateChannelWithIssuedToken(token);

但我的要求是使用生成的ServiceReference。:(

4

3 回答 3

3

您应该像这样使用创建的频道:

private static void CallServiceReference(SecurityToken token)
{
    ServiceReference1.ClaimsServiceContractClient svcRef = 
        new ServiceReference1.ClaimsServiceContractClient();

    svcRef.ChannelFactory.Credentials.SupportInteractive = false;
    var svcChannel = svcRef.ChannelFactory.CreateChannelWithIssuedToken(token);
    var claims = svcChannel.GetClaims();
}
于 2014-03-26T09:17:11.923 回答
0

我认为您可以使用从服务参考生成的代理的唯一方法是,如果您将客户端配置为自动请求令牌并在进行服务调用之前在您创建的代理实例上设置适当的 ClientCredentials 属性。

我们正在使用一个已发布的令牌,我们在我从事的项目中缓存在客户端上,但随后我们必须使用通道工厂 CreateChannelWithIssuedToken,就像您描述的那样。

顺便说一句,这是在 .NET 4.0 中使用 WIF 时。如果在 .NET 4.5 上运行,也许还有其他选择。

于 2013-02-13T21:43:19.683 回答
0

有时您没有引用的客户端存根 DLL,那么您可以使用反射来动态加载和调用它。这是使用已颁发令牌创建客户端的反射版本:

//Our goal is to get a client obj from reflection
//var obj = client.ChannelFactory.CreateChannelWithIssuedToken(token);

double value1 = 2;
double value2 = 3;
//this line needs to be changed to be created from reflection if needed
CalculatorClient cc = new CalculatorClient("WS2007FederationHttpBinding_ICalculator"); var pi = cc.GetType().GetProperty("ChannelFactory"); //proprety 
var factoryObj = pi.GetValue(cc);
var mi = factoryObj.GetType().GetMethod("CreateChannelWithIssuedToken", new Type[] { typeof(SecurityToken)}); //method info
var clientObj = mi.Invoke(factoryObj, new object[] { token });
mi = clientObj.GetType().GetMethod("Add"); //another method info
var result = mi.Invoke(clientObj, new Object[] { 2, 3 });
Console.WriteLine("Add({0},{1}) = {2}", value1, value2, Convert.ToDouble(result));
于 2019-08-05T03:27:06.117 回答