Как использовать IssuedToken в клиенте со ссылкой на службу WCF

У меня есть приложение WinForms со ссылкой на службу, созданную из службы WCF, которая использует привязку WS2007FederationHttpBinding. Я не могу понять, почему следующее не работает.

Мое приложение WinForms вызывает службу WCF, использующую Thinktecture.IdentityServer, настроенную для обработки токенов типа 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(); 
    }

Вот файл app.config клиента winforms для справки по сервису:

<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. :(




Ответы (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();
}
person maland    schedule 26.03.2014

Я думаю, что единственный способ использовать сгенерированный прокси из справочника службы - это настроить клиента на автоматический запрос токена и установить соответствующее свойство ClientCredentials на созданном вами экземпляре прокси перед вызовом службы.

Мы используем выпущенный токен, который мы храним в кэше на клиенте в проекте, над которым я работаю, но затем мы должны использовать фабрику каналов CreateChannelWithIssuedToken, как вы описываете.

Кстати, это при использовании WIF в .NET 4.0. Возможно, есть другие варианты, если вы работаете на .NET 4.5.

person Per Salmi    schedule 13.02.2013

Иногда у вас нет указанной клиентской библиотеки 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));
person tedyyu    schedule 05.08.2019