WCF в IIS, используя MSMQ в режиме рабочей группы
Я пробовал 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 Directory. Фабрика канала или сервисный хост не могут быть открыты.
Вот что я пробовал:
предоставить всем полный доступ (включая анонимный вход) к очереди
Настройка приложения для использования определенной привязки из файла конфигурации, используя:
<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 в качестве меры безопасности. Тем не менее, в моем конфигурационном файле безопасность не установлена. Любые идеи о том, откуда происходит это переопределение поведения?
Разрешение:
Я чувствую себя действительно глупо с одной стороны, но я чувствую, что есть возможности для улучшения с другой стороны. Короткая версия состоит в том, что я испортил значение в атрибуте name в элементе service:
<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 ответа
Попробуйте эти настройки... useActiveDirectory
должно быть ложным по умолчанию, но попробуйте. Режим аутентификации устанавливается на самом транспорте, поэтому msmqAuthenticationMode
должен быть установлен на "нет". 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 или использовать методы защиты сообщений в рабочей группе.
Также не забудьте, что настройки для сервера и клиента должны совпадать.
НТН,
Джеймс
Извините за постоянные обновления, мое внимание к деталям сегодня кажется немного низким
: П
Не уверен, что это решит вашу конкретную проблему здесь, но есть действительно хорошая серия из трех статей в блоге Тома Холландера:
- MSMQ, WCF и IIS: как заставить их играть хорошо (часть 1 из 3)
- MSMQ, WCF и IIS: как заставить их играть хорошо (часть 2 из 3)
- MSMQ, WCF и IIS: заставить их играть хорошо (часть 3 из 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>
Когда мы столкнулись с проблемой<security mode="None">
работал в тестовой среде.
Во время окончательной доставки даже это не сработало.. Наконец этот сработал
<security>
<transport
msmqAuthenticationMode="None"
msmqProtectionLevel="None"/>
</security>
Деннис ван дер Стелт предоставил хороший образец на WCF + MSMQ.
Вы также можете быть заинтересованы в этом Q/A на MSDN:
Вопрос: Когда я запускаю образец, который использует привязку по умолчанию в режиме рабочей группы, сообщения, похоже, отправляются, но никогда не принимаются получателем.
О: По умолчанию сообщения подписываются с использованием внутреннего сертификата MSMQ, для которого требуется служба каталогов Active Directory. В режиме рабочей группы, поскольку Active Directory недоступен, подписать сообщение не удается. Таким образом, сообщение попадает в очередь недоставленных сообщений, и указывается причина сбоя, например "Плохая подпись".
Обходной путь должен отключить безопасность. Это можно сделать, установив Mode = None, чтобы он работал в режиме рабочей группы.
Другой обходной путь - получить MsmqTransportSecurity из свойства Transport, установить для него значение Certificate и установить сертификат клиента.
Еще один обходной путь - установить MSMQ с интеграцией с Active Directory.