IIS 中的 WCF,在工作组模式下使用 MSMQ

Posted

技术标签:

【中文标题】IIS 中的 WCF,在工作组模式下使用 MSMQ【英文标题】:WCF in IIS, using MSMQ in workgroup mode 【发布时间】:2011-05-28 10:52:07 【问题描述】:

我一直在用 WCF 试用 MSMQ,但我似乎无法让它正常工作。通过使用 WCF 和服务引用,我让客户端(将消息发送到队列)正常工作。执行此操作的代码或多或少是这样的:

static void Main(string[] args)

    var client = new MsmqServiceReference.MsmqContractClient();
    client.SendMessage("TEST");
    client.Close();
    Console.ReadKey();

MsmqContractClient 是我添加服务引用时由 Visual Studio 生成的代理。 app.config 中的端点指向一个 msmqueue:

<client>
  <endpoint 
    address="net.msmq://localhost/private/MsmqService/MsmqService.svc"
    binding="netMsmqBinding"  
    bindingConfiguration="MsmqBindingNonTransactionalNoSecurity"
    contract="MsmqServiceReference.IMsmqContract" name="MsmqService" />
</client>

这行得通,正在将消息发布到队列中。

现在我正在尝试让服务真正运行,但我不断收到此错误:

绑定验证失败,因为 绑定的 MsmqAuthenticationMode 属性设置为 WindowsDomain 但 MSMQ 与 Active 一起安装 目录集成已禁用。这 通道工厂或服务主机不能 被打开。

我尝试过的事情是:

授予每个人对队列的完全访问权限(包括匿名登录)

将应用配置为使用配置文件中的特定绑定:

<bindings>
  <netMsmqBinding>
     <binding name="MsmqBindingNonTransactionalNoSecurity" 
              deadLetterQueue="Custom" 
              exactlyOnce="false">
       <security mode="None" />
     </binding>
  </netMsmqBinding>
</bindings>

我尝试在我自己的帐户和管理员帐户下在 IIS (7) 中运行应用程序池

让我难过的是,它一直试图说服我我正在尝试使用 WindowsDomain 身份验证来运行它。我说过我不想在安全模式设置为无的情况下这样做,对吧?

目前我的应用只是一个 webforms asp.net 网站,其中添加了 WCF 服务。

如果有人至少能指出我正确的方向,我将非常感激,因为我已经在这方面花费了太多时间。


似乎配置被忽略或覆盖。完整的错误信息:

WebHost failed to process a request.
 Sender Information: System.ServiceModel.Activation.HostedHttpRequestAsyncResult/63721755
 Exception: System.ServiceModel.ServiceActivationException: The service '/MsmqService/MsmqService.svc' cannot be activated due to an exception during compilation.  The exception message is: Binding validation failed because the binding's MsmqAuthenticationMode property is set to WindowsDomain but MSMQ is installed with Active Directory integration disabled. The channel factory or service host cannot be opened.. ---> System.InvalidOperationException: Binding validation failed because the binding's MsmqAuthenticationMode property is set to WindowsDomain but MSMQ is installed with Active Directory integration disabled. The channel factory or service host cannot be opened.
   at System.ServiceModel.Channels.MsmqVerifier.VerifySecurity(MsmqTransportSecurity security, Nullable`1 useActiveDirectory)
   at System.ServiceModel.Channels.MsmqVerifier.VerifyReceiver(MsmqReceiveParameters receiveParameters, Uri listenUri)
   at System.ServiceModel.Channels.MsmqTransportBindingElement.BuildChannelListener[TChannel](BindingContext context)
   at System.ServiceModel.Channels.BindingContext.BuildInnerChannelListener[TChannel]()
   at System.ServiceModel.Channels.MessageEncodingBindingElement.InternalBuildChannelListener[TChannel](BindingContext context)
   at System.ServiceModel.Channels.BinaryMessageEncodingBindingElement.BuildChannelListener[TChannel](BindingContext context)
   at System.ServiceModel.Channels.BindingContext.BuildInnerChannelListener[TChannel]()
   at System.ServiceModel.Channels.Binding.BuildChannelListener[TChannel](Uri listenUriBaseAddress, String listenUriRelativeAddress, ListenUriMode listenUriMode, BindingParameterCollection parameters)
   at System.ServiceModel.Description.DispatcherBuilder.MaybeCreateListener(Boolean actuallyCreate, Type[] supportedChannels, Binding binding, BindingParameterCollection parameters, Uri listenUriBaseAddress, String listenUriRelativeAddress, ListenUriMode listenUriMode, ServiceThrottle throttle, IChannelListener& result, Boolean supportContextSession)
   at System.ServiceModel.Description.DispatcherBuilder.BuildChannelListener(StuffPerListenUriInfo stuff, ServiceHostBase serviceHost, Uri listenUri, ListenUriMode listenUriMode, Boolean supportContextSession, IChannelListener& result)
   at System.ServiceModel.Description.DispatcherBuilder.InitializeServiceHost(ServiceDescription description, ServiceHostBase serviceHost)
   at System.ServiceModel.ServiceHostBase.InitializeRuntime()
   at System.ServiceModel.ServiceHostBase.OnBeginOpen()
   at System.ServiceModel.ServiceHostBase.OnOpen(TimeSpan timeout)
   at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
   at System.ServiceModel.Channels.CommunicationObject.Open()
   at System.ServiceModel.ServiceHostingEnvironment.HostingManager.ActivateService(String normalizedVirtualPath)
   at System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath)
   --- End of inner exception stack trace ---
   at System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result)
   at System.ServiceModel.Activation.HostedHttpRequestAsyncResult.End(IAsyncResult result)
 Process Name: w3wp
 Process ID: 5660

我尝试弄清楚使用 Reflector 会发生什么,但似乎以某种方式将 MsmqTransportBindingElement 传递到通道构建过程中,这确信它必须使用 WindowsDomain 作为安全措施。但是,我在我的配置文件中将安全设置为无。关于这种覆盖行为来自哪里的任何想法?


分辨率:

一方面我觉得自己很愚蠢,但另一方面我觉得还有改进的余地。 简短的版本是我弄乱了服务元素的“名称”属性中的值:

<services>
  <service name="WcfService.MsmqService">
    <!--        <endpoint binding="mexHttpBinding" contract="IMetadataExchange" />-->
    <endpoint name="msmq" 
            address="net.msmq://localhost/private/MsmqService/MsmqService.svc"
            binding="netMsmqBinding" 
            bindingConfiguration="NoSecurity"
            contract="WcfService.IMsmqContract" />
  </service>
</services>

名称与我的客户端上的名称相同,但是客户端具有由 Visual Studio 生成的绑定。我给它起了一个不同的名字(MsmqService),所以名字的值是'MsmqService.MsmqService'。

让我感到困扰的是,我没有收到任何警告,说明我正在配置一个不存在的服务,或者任何迹象表明我正在使用该服务的默认配置。如果框架至少会在我正在使用默认值的地方生成警告,或者打开某种形式的严格模式的选项,那将是非常好的。不管怎样,感谢您的所有意见,我会再用头撞墙几次。

是的,你现在可以指指点点笑了 ;-)

【问题讨论】:

你是个传奇!我已经为我的配置倾注了几个小时,才意识到我犯了和你一样的错误! 哈哈,感谢我搞砸并找出我的错误帮助了另一个开发人员:) 把我的头撞在墙上,直到我找到了这个。实际问题和错误消息之间是否有任何联系... 我也遇到了同样的问题。没有意识到我的服务名称不正确,产生了这个误导性错误! +1 【参考方案1】:

试试这些设置...useActiveDirectory 默认应该是 false,但是试试看。身份验证模式在传输本身上设置,因此msmqAuthenticationMode 应设置为“无”。 msmqProtectionLevelclientCredentialType 听起来很相关,所以我也把它们扔在那里 :)

<bindings>
  <netMsmqBinding>
     <binding name="MsmqBindingNonTransactionalNoSecurity" 
          deadLetterQueue="Custom"
          useActiveDirectory="false" 
          exactlyOnce="false">
       <security mode="None">
         <transport 
            msmqAuthenticationMode="None"
            msmqProtectionLevel="None"
            clientCredentialType="None"/>
       </security>
     </binding>
  </netMsmqBinding>
</bindings>

我担心会删除所有安全性,但是...如果您在域中,则应安装带有 Active Directory 集成的 MSMQ,或使用工作组方法来保护消息。

另外,不要忘记,服务器和客户端的设置必须匹配。

HTH, 詹姆斯

抱歉持续更新,今天我对细节的关注似乎有点低 :P

【讨论】:

当然,我同意删除所有安全性对生产环境不利。但是对于这个工作的简单演示,我需要让它尽可能简单地运行。现在要试试你的设置。 嗯,还是不行。打算在另一台机器上尝试,也许这是我的环境。 +1 提到安全性应该关闭;-) 不得不一直挖掘才能找到这个,但可以在这里找到 netMsmqBinding 的架构:msdn.microsoft.com/en-us/library/ms731380.aspx 嗯,您能发布您的完整客户端和服务器配置吗? `clientCredentialType="None"` 现在无法在 .net 4.5.1 中设置【参考方案2】:

不确定这是否能解决您的具体问题,但 Tom Hollander 有一个非常好的三部分博客文章系列:

MSMQ, WCF and IIS: Getting them to play nice (part 1 of 3) MSMQ, WCF and IIS: Getting them to play nice (part 2 of 3) MSMQ, WCF and IIS: Getting them to play nice (part 3 of 3)

另外,由于 Active Directory 的东西似乎是问题所在,您是否尝试过告诉您的 MSMQ 绑定不要使用 AD ??

<bindings>
  <netMsmqBinding>
     <binding name="MsmqBindingNonTransactionalNoSecurity" 
              deadLetterQueue="Custom" exactlyOnce="false"
              useActiveDirectory="false">   <== try this setting here!
        <security mode="None" />
     </binding>
  </netMsmqBinding>
</bindings>

【讨论】:

更新链接:第 1 部分,dzone.com/articles/msmq-wcf-and-iis-getting-them- 第 2 部分,dzone.com/articles/msmq-wcf-and-iis-getting-them--0 第 3 部分,dzone.com/articles/msmq-wcf-and-iis-getting-them--1【参考方案3】:

当我们遇到问题时 &lt;security mode="None"&gt;在测试环境中工作。

在最终交付期间,即使那样也没有用..终于这个工作了

<security>
<transport
msmqAuthenticationMode="None"
msmqProtectionLevel="None"/>
</security>

【讨论】:

【参考方案4】:

Dennis van der Stelt 在 WCF + MSMQ 上提供了一个很好的示例。

您可能还对MSDN 上的此 Q/A 感兴趣:

问:当我在工作组模式下运行使用默认绑定的示例时,消息似乎已发送但接收方从未收到。

答:默认情况下,使用需要 Active Directory 目录服务的 MSMQ 内部证书对消息进行签名。在工作组模式下,由于 Active Directory 不可用,因此对消息进行签名会失败。因此消息进入死信队列并指出失败原因,例如“Bad signature”。

解决方法是关闭安全性。这是通过设置 Mode = None 使其在工作组模式下工作来完成的。

另一种解决方法是从 Transport 属性中获取 MsmqTransportSecurity 并将其设置为 Certificate,然后设置客户端证书。

另一个解决方法是安装带有 Active Directory 集成的 MSMQ。

【讨论】:

我现在使用它的方式基本上是向服务器发送一些东西。这部分工作正常,消息最终进入队列(而不是死信)。

以上是关于IIS 中的 WCF,在工作组模式下使用 MSMQ的主要内容,如果未能解决你的问题,请参考以下文章

实现 TCP、命名管道和 MSMQ 的传统方法是啥?

WCF net.msmq 服务自动激活

WCF msmq 事务和工作单元

Web Service ,WCF以及Web API的对比

如何处理 WCF 的 MSMQ 绑定中的消息失败

WCF IIS 服务器 500 错误 检测到在集成的托管管道模式下不适用的ASP.NET设置的解决方法(转)