我有一个BizTalk WCF-Custom接收位置,我已添加了自定义行为:
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接收位置轮询Service Bus时,我在事件日志中看到以下内容:
适配器“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-Messaging适配器的流量,该适配器按预期工作。区别在于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 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 });
这是一个返回Task的异步方法。是否阻止对此任务的结果以某种方式不能在某些情况下执行预期,这会以某种方式搞乱WCF通道的配置?正如我所说的,我确信这段代码会运行并分配TokenProvider。我现在只是不确定何时运行。
答案 0 :(得分:2)
<强> D'OH!强>
我忽略了,我们仍然在解决方案中使用的旧版本的Microsoft.ServiceBus.dll与(同样旧的)本地版本的Service Bus(Windows Server的Service Bus)互操作是引用的版本通过我的项目。无论出于何种原因,这个版本都没有做到它应该做的事情,也没有任何迹象表明它绕过了预期的行为。更新以获得Service Bus的当前NuGet包可以解决问题。