Подтвердить что ты не робот

WCF в IIS, используя MSMQ в режиме рабочей группы

Я тестировал MSMQ с WCF, но я не могу заставить его работать нормально. У меня есть клиент (который отправляет сообщения в очередь), используя WCF и ссылку на службу. Код, который делает это, более или менее:

static void Main(string[] args)
{
    var client = new MsmqServiceReference.MsmqContractClient();
    client.SendMessage("TEST");
    client.Close();
    Console.ReadKey();
}

Где MsmqContractClient - прокси, созданный визуальной студией, когда я добавляю ссылку на службу. Конечная точка в 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 Интеграция каталогов отключена. канал factory или хост службы не может открывается.

Вещи, которые я пробовал:

  • предоставить всем полный доступ (включая анонимный вход в систему) в очередь

  • настройка приложения для использования конкретной привязки из файла конфигурации с помощью:

    <bindings>
      <netMsmqBinding>
         <binding name="MsmqBindingNonTransactionalNoSecurity" 
                  deadLetterQueue="Custom" 
                  exactlyOnce="false">
           <security mode="None" />
         </binding>
      </netMsmqBinding>
    </bindings>
    
  • Я попробовал запустить пул приложений в IIS (7) под своей учетной записью и учетной записью администратора

Что пень меня, так это то, что он пытается убедить меня, что я пытаюсь запустить его с помощью проверки подлинности WindowsDomain. Я заявил, что я НЕ хотел этого делать, когда в режиме безопасности установлено значение none, правильно?

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


Разрешение:

Я чувствую себя очень глупо, с одной стороны, но с другой стороны я чувствую, что есть возможность для улучшения. Короткий вариант заключается в том, что я испортил значение в атрибуте "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>

Название было таким же, как у моего клиента, однако у клиента были привязки, созданные визуальной студией. Я дал ему другое имя (MsmqService), поэтому значение имени было "MsmqService.MsmqService".

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

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

4b9b3361

Ответ 1

Попробуйте эти настройки... useActiveDirectory по умолчанию будет ложным, но попробуйте. Режим аутентификации устанавливается на самом транспорте, поэтому 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 или использовать методы Workgroup для защиты сообщений.

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

HTH,
Джеймс

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

Ответ 2

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

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

Ответ 3

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

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

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

Ответ 4

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

Вы также можете быть заинтересованы в этом Q/A на MSDN:

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

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

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

Еще одно решение - получить MsmqTransportSecurity из свойства Transport и установить его в Certificate и установить сертификат клиента.

Еще одним обходным решением является установка MSMQ с интеграцией в Active Directory.