2016-12-01 138 views
9

我有一個BizTalk WCF-定製接收位置到我添加了一個自定義行爲:爲了簡潔省略爲什麼WCF會忽略我的TokenProvider?

這是從在https://code.msdn.microsoft.com/How-to-integrate-BizTalk-07fada58#content發現樣品適於

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

參數設置代碼 - 這作者在BizTalk社區得到了廣泛的尊重,並且這類代碼已經使用了好幾年。我所做的全部工作就是改變他使用的方法,這被證明是有效的,可以替代一個不同的TokenProvider。

我可以通過調試看到此代碼運行,並將具有正確參數的TransportClientEndpointBehavior添加到通道中。但是,當BizTalk接收位置輪詢服務總線時,我在事件日誌中看到以下內容:

適配器「WCF-Custom」引發了錯誤消息。詳細信息「System.UnauthorizedAccessException:40102:Missing authorization token,Resource: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 ---> 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服務總線端點將返回該錯誤消息,只是因爲沒有使用令牌提供者。爲什麼會在通道忽略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,我相信我已經找到了實際創建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()返回null(爲什麼?)

編輯#3:

我已編譯並運行示例代碼,並可以正常工作。我的代碼之間的唯一區別顯著他是我的包括召喚出Azure的關鍵庫行:

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被分配到它應該在的地方。我唯一想到的另一個想法是,在正常的服務總線場景中可能有一個特殊的Channel Factory來完成這個工作,而BizTalk可能會有一個bog標準的ChannelFactory或一個BizTalk-具體的一個,其中任何一個都不會知道關於該特殊邏輯的任何內容我現在無法進行調查,但我會在某些時候跟進這種可能性。 –

+0

我正在通過一個應該證明前面的斷言的例子 - 我越來越有信心確實如此。 [這個例子](https://code.msdn.microsoft.com/Brokered-Messaging-WCF-0a526451)表明,爲了Service Bus方案在WCF中工作,必須調用CustomBinding.BuildChannelFactory;這會委託給傳輸綁定元素來實際創建通道。在單元測試中調用此方法將返回一個ServiceBusChannelFactory - WCF適配器不會**執行此操作。我相信這就是Paolo的SessionChannelBindingElement重要性的原因。 –

回答

2

D'OH!

我忘了把認識到很老的版本Microsoft.ServiceBus.dll我們仍然有處所版本服務總線(服務總線的Windows服務器)用於與(同樣舊)互操作的解決方案是一個由我的項目引用。無論出於何種原因,這個版本都不會做它應該做的事情,也沒有給出任何跡象表明它正在繞過預期的行爲。更新以使Service Bus的當前NuGet包修復問題。

+0

我投你的勇氣和意願回來並回答。這關閉了我們餘下的想法中可能一直存在的問題的循環。謝謝。 –