处理死信队列中的MSMQ无效签名错误

时间:2014-08-26 00:47:29

标签: c# wcf windows-7 msmq windows-server-2012-r2

首先我要说明这个问题非常类似于以下帖子:MSMQ messages received but not delivered Windows 2008 R2。不过,这篇文章还不清楚是什么解决了这个问题。

我的场景:

我有两个实体A和B,它们互为服务和客户。 我还有另一个实体C,它充当B的客户。

  1. A向B发送消息,注册它的URI。
  2. 在某些事件中,C向B发送消息。
  3. 收到来自C的消息后,B向A发送消息。
  4. 所有邮件都在事务处理队列中发送。当我仅在localhost(Windows 7专业版)上运行上述场景时,一切都很好:所有消息都被正确发送和接收。

    现在问题出现在以下设置中,其中A和C在我的Windows 7专业版上。 machine和B位于Windows Server 2012 R2上。

    对于步骤1和2,一切都是合理的:发送和接收消息。 现在在3中,当B向A发送消息时,A永远不会收到消息。 MSMQ的事件日志告诉我B确实发送了消息,而A的最后一个事件是:"消息来自网络"。

    当我检查B上的Transacted Dead Letter队列时,我现在可以看到我的所有消息都有"无效的签名"错误。从我收集到的内容来看,这个错误似乎与认证问题有关,所以这就是我在A&#t>配置中所做的:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
      </startup>
      <appSettings>
        <!-- use appSetting to configure MSMQ queue name -->
        <add key="queueName" value=".\private$\MainOrchestrator/MainOrchestratorService" />
        <add key="ClientSettingsProvider.ServiceUri" value="" />
      </appSettings>
      <system.serviceModel>
        <services>
          <service name="MachineCommunication.Orchestrators.MainOrchestrator.MainService" behaviorConfiguration="DefaultBehavior">
            <host>
              <baseAddresses>
                <add baseAddress="http://localhost:13000/" />
              </baseAddresses>
            </host>
            <!-- Define NetMsmqEndpoint -->
            <endpoint address="net.msmq://localhost/private/MainOrchestrator/MainOrchestratorService" binding="netMsmqBinding" bindingConfiguration="TransactedBinding" contract="MachineCommunication.Contracts.OrchestratorContracts.IOrchestratorService" />
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
          </service>
        </services>
        <client>
          <endpoint address="net.msmq://windowsserver2012address/private/Zeiss/ZeissAdapterService" binding="netMsmqBinding" bindingConfiguration="TransactedBinding" contract="IAdapterService" name="ZeissAdapter" />
        </client>
        <behaviors>
          <serviceBehaviors>
            <behavior name="DefaultBehavior">
              <serviceDebug includeExceptionDetailInFaults="true" />
              <serviceMetadata httpGetEnabled="true" />
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <bindings>
          <netMsmqBinding>
            <binding name="TransactedBinding" deadLetterQueue="System" useActiveDirectory ="False">
              <security mode="None">
                <message clientCredentialType="None"/>            
                <transport msmqAuthenticationMode="None" msmqProtectionLevel="None"  />
              </security>          
            </binding>
          </netMsmqBinding>
        </bindings>
      </system.serviceModel>
    </configuration>
    

    我也按如下方式创建队列:

        MessageQueue queue;
    
        if (!MessageQueue.Exists(queueName))
        {
            queue = MessageQueue.Create(queueName, true);
            queue.Authenticate = false;
    
            queue.SetPermissions("ANONYMOUS LOGON",
                MessageQueueAccessRights.FullControl,
                AccessControlEntryType.Allow);
        }
    

    然而,仍然有#34;无效签名&#34;问题。如果有人能说清楚这一点,

    很多,非常感谢提前!

2 个答案:

答案 0 :(得分:3)

找到解决方案。大多数关于交易死信队列中“无效签名”错误的帖子或多或少详细解释了它通常如何涉及接收端的权限问题(在这种情况下,是A队列的安全配置)。在我的情况下,问题也在发送端撒谎。即:

  

如果您收到“签名无效”错误,则表示您的错误   频道正在尝试发送经过身份验证的消息。

(source)

为了完整起见,这是我目前的A:

安全配置
      <netMsmqBinding>
        <binding name="TransactedBinding" deadLetterQueue="System" useActiveDirectory ="False">
          <security mode="None">
            <message clientCredentialType="None"/>            
            <transport msmqAuthenticationMode="None" msmqProtectionLevel="None"  />
          </security>          
        </binding>
      </netMsmqBinding>

A的服务端点使用以下内容引用此绑定:

<endpoint address="net.msmq://localhost/private/MainOrchestrator/MainOrchestratorService" binding="netMsmqBinding" bindingConfiguration="TransactedBinding" contract="MachineCommunication.Contracts.OrchestratorContracts.IOrchestratorService" />

虽然这一切都很好,但是还不够。

在B方面,我将消息发送到:

            NetMsmqBinding msmqCallbackBinding = new NetMsmqBinding();
            EndpointAddress epAddr = new EndpointAddress(client.clientUri);
            OrchestratorServiceClient orchestratorServiceClient = new OrchestratorServiceClient(msmqCallbackBinding, epAddr);                    

            using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
            {
                sendAction(orchestratorServiceClient);
                scope.Complete();
            }
            orchestratorServiceClient.Close();

问题在于NetMsmqBinding。默认情况下,此绑定似乎尝试使用身份验证,这就是失败的原因。替换:

NetMsmqBinding msmqCallbackBinding = new NetMsmqBinding();

使用:

NetMsmqBinding msmqCallbackBinding = new NetMsmqBinding(NetMsmqSecurityMode.None);

解决了这个问题。

答案 1 :(得分:1)

我试图添加评论,但我没有足够的“代表”。这不是一个答案,但我相信你的问题在于MSDTC。