wcf - 为什么 WCF 会忽略我的 TokenProvider?

标签 wcf biztalk azureservicebus azure-servicebus-queues

我有一个 BizTalk WCF 自定义接收位置,我已向其中添加了自定义行为:

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 添加到了 channel 中。但是,当 BizTalk 接收位置轮询服务总线时,我在事件日志中看到以下内容:

The adapter "WCF-Custom" raised an error message. Details "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: 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



我看不出 Azure 服务总线端点会返回此错误消息的任何原因,除非是因为未使用 token 提供程序。为什么 channel 会忽略 TokenProvider,我必须做些什么才能正确传递 token ?

编辑:

我已经检查了相关端口的原始 WCF 消息流量以及使用 SB-Messaging 适配器的端口,它按预期工作。不同之处在于 SB-Messaging 适配器的消息包含一个 SOAP header ,如:
<Authorization xmlns="http://schemas.microsoft.com/servicebus/2010/08/protocol/">SharedAccessSignature sr=[really long encoded string]</Authorization>而我的自定义绑定(bind)端口的消息没有。所以问题确实是缺少授权 SOAP header ;但问题仍然存在 - 为什么 channel 不添加此 header ?

编辑#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 header 有两个原因:
  • 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 channel 的配置?正如我所说,我确信这段代码运行并分配了 TokenProvider。我现在只是不确定它何时运行。

    最佳答案

    哦!

    我没有意识到,我们仍然在与(同样旧的)本地版本的服务总线(Windows Server 的服务总线)互操作的解决方案中使用的旧版本的 Microsoft.ServiceBus.dll 是我的项目引用的版本.无论出于何种原因,这个版本只是没有做它应该做的事情,并且没有给出任何迹象表明它正在绕过预期的行为。更新以使用服务总线的当前 NuGet 包可解决此问题。

    关于wcf - 为什么 WCF 会忽略我的 TokenProvider?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40909769/

    相关文章:

    windows - WCF 异常 : . ..此服务需要 'Anonymous' 身份验证,但未为托管此服务的 IIS 应用程序启用

    c# - 用于在两个进程之间进行通信的.net框架

    biztalk - BT2006 R2 到 BT2013 R2 的迁移方法

    rest - BizTalk Server 2013 休息错误处理

    azure - 如何删除和重命名已在 Azure 服务总线命名空间中创建的订阅筛选器?

    c# - 如何将 WCF 客户端代理生成的类中的方法标记为虚拟

    powershell - 尝试在 'BizTalk'提供程序上执行InitializeDefaultDrives操作失败

    azure - 手动将消息发布到死信队列?

    apache-kafka - Azure 服务总线上的 Kafka 表相当于什么?

    c# - WCF 中的证书验证