2016-12-01 3 views
9

У меня есть BizTalk WCF-Выборочный получить место, в которое я добавил пользовательское поведение:Почему WCF игнорирует мой TokenProvider?

public class SasTokenProviderEndpointBehavior : BehaviorExtensionElement, IEndpointBehavior 
    { 
     public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) 
     { 
       var tokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider(sharedAccessSecretName, sharedAccessKey); 
       bindingParameters.Add(new TransportClientEndpointBehavior { TokenProvider = tokenProvider });   
     } 
    } 
} 

параметра код установки для краткости опускает

Это адаптированная из образца найденного в https://code.msdn.microsoft.com/How-to-integrate-BizTalk-07fada58#content - это автор пользуется большим уважением в сообществе BizTalk, и такой код используется в течение нескольких лет. Все, что я делаю, - это адаптация метода, который он использует, который, как доказано, работает, чтобы заменить другого TokenProvider.

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

Адаптер «WCF-Custom» поднял сообщение об ошибке. Подробности "System.UnauthorizedAccessException: 40102: Отсутствует токен авторизации, Ресурс: sb: // [namespace] .servicebus.windows.net/[queue]. TrackingId: 452c2534-d3e6-400f-874f-09be324e9e11_G27, SystemTracker: [namespace]. servicebus.windows.net:[queue], Временная метка: 12/1/2016 11:38:56 AM ---> System.ServiceModel.FaultException: 40102: Отсутствует токен авторизации, Ресурс: sb: // [namespace] .servicebus .windows.net/[queue]. TrackingId: 452c2534-d3e6-400f-874f-09be324e9e11_G27, SystemTracker: [namespace] .servicebus.windows.net: [queue], Timestamp: 12/1/2016 11:38:56 AM

Я не вижу никаких причин, что конечная точка Azure Service Bus возвратит сообщение об ошибке, за исключением того, потому что маркер поставщик не используется. Почему бы канал игнорировать TokenProvider и что мне нужно сделать, чтобы пройти токен правильно?

редактировать:

Я проверил необработанный трафик сообщений WCF для порта в вопросе, а также один с помощью адаптера SB-сообщений, который работает, как ожидалось. Разница заключается в том, что сообщения адаптера SB-Messaging содержат заголовок SOAP, например:

<Authorization xmlns="http://schemas.microsoft.com/servicebus/2010/08/protocol/">SharedAccessSignature sr=[really long encoded string]</Authorization> и сообщения моего пользовательского связующего порта нет. Поэтому верно, что проблема заключается в отсутствии заголовка SOAP для авторизации; но вопрос сохраняется - почему не канал, добавляющий этот заголовок?

редактировать # 2:

Я декомпилированы Microsoft.ServiceBus.dll, и я полагаю, что я нашел класс, который на самом деле создает messsage WCF, Microsoft.ServiceBus.Messaging.Sbmp.SbmpMessageCreator. Он имеет следующий метод:

private Message CreateWcfMessageInternal(string action, object body, bool includeToken, string parentLinkId, RetryPolicy policy, TrackingContext trackingContext, RequestInfo requestInfo) 
    { 
     Message message = Message.CreateMessage(this.messageVersion, action, body); 
     MessageHeaders headers = message.Headers; 
     headers.To = this.logicalAddress; 
     string sufficientClaims = this.GetSufficientClaims(); 
     if (this.linkInfo != null) 
     { 
     if (!string.IsNullOrEmpty(this.linkInfo.TransferDestinationEntityAddress)) 
     { 
      SecurityToken authorizationToken = this.GetAuthorizationToken(this.linkInfo.TransferDestinationEntityAddress, sufficientClaims); 
      if (authorizationToken != null) 
      { 
      SimpleWebSecurityToken webSecurityToken = (SimpleWebSecurityToken) authorizationToken; 
      if (webSecurityToken != null) 
       this.linkInfo.TransferDestinationAuthorizationToken = webSecurityToken.Token; 
      } 
     } 
     this.linkInfo.AddTo(headers); 
     } 
     if (includeToken) 
     { 
     ServiceBusAuthorizationHeader authorizationHeader = this.GetAuthorizationHeader(sufficientClaims); 
     if (authorizationHeader != null) 
      headers.Add((MessageHeader) authorizationHeader); 
     } 
     if (this.messagingFactory.FaultInjectionInfo != null) 
     this.messagingFactory.FaultInjectionInfo.AddToHeader(message); 
     if (!string.IsNullOrWhiteSpace(parentLinkId)) 
     message.Properties["ParentLinkId"] = (object) parentLinkId; 
     if (trackingContext != null) 
     TrackingIdHeader.TryAddOrUpdate(headers, trackingContext.TrackingId); 
     MessageExtensionMethods.AddHeaderIfNotNull<RequestInfo>(message, "RequestInfo", "http://schemas.microsoft.com/netservices/2011/06/servicebus", requestInfo); 
     return message; 
    } 

Так думать об этом логически, есть две причины, по которым заголовок Authorization будет отсутствовать:

  • includeToken является ложным (Почему это так?)
  • GetAuthorizationHeader() возвращает нуль (почему?)

редактировать # 3:

Я скомпилировал и запустил пример кода, и это работает.Единственное существенное различие между моим кодом и его в том, что шахта включает в себя линию, которая взывает к Azure Key Vault:

var kv = new KeyVaultClient(this.GetAccessToken); 
var key = kv.GetSecretAsync(this.KeyVaultUri.AbsoluteUri, this.SharedAccessSecretName).Result; 
var sharedAccessKey = key.Value; 
var tokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider(
      this.SharedAccessSecretName, 
      sharedAccessKey); 
bindingParameters.Add(new TransportClientEndpointBehavior { TokenProvider = tokenProvider }); 

Это асинхронный метод, который возвращает задачу. Может ли быть, что блокирование результата этой Задачи каким-то образом не делает того, что можно было бы ожидать в определенных ситуациях, и это каким-то образом испортило конфигурацию канала WCF? Как я уже сказал, я уверен, что этот код работает и назначает TokenProvider. Я просто не уверен , когда он работает.

+0

Вы пробовали отладку, подключив Visual Studio к экземпляру узла, в котором работает порт? – Dijkgraaf

+0

@ Dijkgraaf Да, вот как я могу доказать себе, что TokenProvider назначен там, где он должен быть. Единственная другая идея, которая произошла со мной, заключается в том, что может случиться так, что в обычных сценариях Service Bus есть специальная фабрика каналов, которая делает «что-то» для выполнения этой работы, тогда как предположительно BizTalk будет иметь либо стандартный стандарт ChannelFactory, либо BizTalk- конкретный, ни один из которых не знал бы ничего об этой специальной логике. Я сейчас не в состоянии расследовать, но в какой-то момент я буду следить за этой возможностью. –

+0

Я прорабатываю пример, который должен продемонстрировать предыдущее утверждение - я уверен, что это так. [этот пример] (https://code.msdn.microsoft.com/Brokered-Messaging-WCF-0a526451) предполагает, что для того, чтобы сценарии Service Bus работали в WCF, нужно вызвать CustomBinding.BuildChannelFactory; это делегирует до элемента привязки транспорта, чтобы фактически создать канал. Вызов этого в модульном тесте возвращает ServiceBusChannelFactory - адаптер WCF делает ** не ** делает это. Я считаю, что именно поэтому Пауло «SessionChannelBindingElement» важен. –

ответ

2

D'OH!

Я забыл понять, что очень старая версия Microsoft.ServiceBus.dll, которую мы все еще имеем в решении для взаимодействия с (одинаково старой) версией служебной шины (служебной шины для Windows Server), была один из которых ссылается на мой проект. По какой-то причине эта версия просто не делает то, что она должна, и не дает никаких указаний на то, что она обходит предполагаемое поведение. Обновление, связанное с тем, что текущий пакет NuGet для служебной шины устраняет проблему.

+0

Я проголосовал за вашу храбрость и готовность вернуться и ответить. Это закрывает цикл на том, что могло быть затянутыми вопросами в остальной части нашего сознания. Спасибо. –