WCF в IIS, используя MSMQ в режиме рабочей группы - PullRequest
12 голосов
/ 20 декабря 2010

Я пробовал MSMQ с WCF, но я не могу заставить его работать должным образом. У меня есть клиент (который отправляет сообщения в очередь), с помощью 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. Я заявил, что не хочу этого делать, если для режима безопасности установлено значение none, верно?

Мое приложение на данный момент является просто сайтом 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 в качестве меры безопасности. Тем не менее, в моем конфигурационном файле для безопасности установлено значение none. Любые идеи о том, откуда происходит это переопределение?


Разрешение:

Я чувствую себя действительно глупо с одной стороны, но я чувствую, что есть возможности для улучшения с другой стороны. Короткая версия состоит в том, что я испортил значение в атрибуте name в элементе службы:

<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».

Что меня беспокоит, так это то, что я не получил никакого предупреждения о том, что я настраивал несуществующую службу, или каких-либо указаний на то, что я использую конфигурацию по умолчанию для службы. Было бы очень хорошо, если бы фреймворк хотя бы где-нибудь генерировал предупреждение о том, что я использую значения по умолчанию, или опцию включения какой-либо строгой формы. В любом случае, спасибо за ваш вклад, и я буду биться головой о стену еще несколько раз.

И да, теперь вы можете указывать и смеяться; -)

Ответы [ 4 ]

9 голосов
/ 28 декабря 2010

Попробуйте эти настройки ... useActiveDirectory должно быть false по умолчанию, но попробуйте.Режим аутентификации устанавливается на самом транспорте, поэтому msmqAuthenticationMode должно быть установлено в «none».msmqProtectionLevel и clientCredentialType звучат релевантно, поэтому я тоже их туда закинул:)

<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>

Я бы позаботился об удалении всей защиты, однако ... если вы находитесь в домене, вам следует установить MSMQ с интеграцией с Active Directory или использовать методы защиты сообщений в рабочей группе.

Кроме того, не забудьте, что настройки для сервера и клиента должны совпадать.

HTH,Джеймс

Извините за постоянные обновления, мое внимание к деталям сегодня кажется немного низким: P

2 голосов
/ 15 июня 2012

Когда мы столкнулись с проблемой <security mode="None"> работал в тестовой среде.

Во время окончательной доставки даже это не работало .. Наконец этот работал

<security>
<transport
msmqAuthenticationMode="None"
msmqProtectionLevel="None"/>
</security>
2 голосов
/ 20 декабря 2010

Не уверен, что это решит вашу конкретную проблему здесь, но есть действительно хорошая серия из трех статей в блоге Тома Холландера:

Кроме того, поскольку проблема с 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 голос
/ 20 декабря 2010

Деннис ван дер Стелт предоставил хороший образец на WCF + MSMQ.

Вас также может заинтересовать этот вопрос на MSDN :

В: Когда я запускаю образец, который использует привязку по умолчанию в режиме рабочей группы, сообщения, похоже, отправляются, но никогда не принимаются получателем.

A: По умолчанию сообщения подписываются с использованиемвнутренний сертификат MSMQ, для которого требуется служба каталогов Active Directory.В режиме рабочей группы, поскольку Active Directory недоступен, подписать сообщение не удается.Таким образом, сообщение попадает в очередь недоставленных сообщений, и указывается причина сбоя, например «Плохая подпись».

Обходной путь должен отключить защиту.Это можно сделать, установив Mode = None, чтобы он работал в режиме рабочей группы.

Другой обходной путь - получить MsmqTransportSecurity из свойства Transport, установить для него Certificate и установить сертификат клиента.

Еще один обходной путь - установить MSMQ с интеграцией с Active Directory.

...