Интересная проблема с WCF wsHttpBinding через брандмауэр
-
21-08-2019 - |
Вопрос
У меня есть веб-приложение, развернутое у провайдера интернет-хостинга.Это веб-приложение использует службу WCF, развернутую на сервере IIS, расположенном на сервере приложений моей компании. Чтобы иметь доступ к данным в базе данных компании, сетевые ребята разрешили мне открыть эту службу WCF через брандмауэр по соображениям безопасности.Схема будет выглядеть так.
[Размещенная страница] ---> (Интернет) ---> |Брандмауэр
<Public IP>:<Port-X >
| ---> [IIS с обслуживанием WCF<Comp. Network Ip>:<Port-Y>
]
Я также хотел использовать wsHttpBinding, чтобы воспользоваться его функциями безопасности и зашифровать важную информацию.
Попробовав, я получаю следующую ошибку:
Подробности исключения:System.ServiceModel.EndpointNotFoundException:Сообщение с to 'http: //: /service/wcfservice.svc' не может быть обработано на приемнике из -за несоответствия Addressfilter в EndpointDispatcher.Убедитесь, что endpointaddresses отправителя и приемника согласны.
Проведя небольшое исследование, я обнаружил, что wsHttpBinding использует стандарты WS-адресации, и, прочитав об этом стандарте, я узнал, что заголовок SOAP расширен и теперь включает такие теги, как «MessageID», «ReplyTo», «Action» и «To».
Я предполагаю, что, поскольку конечная точка клиентского приложения указывает IP-адрес и порт брандмауэра, а служба отвечает своим внутренним сетевым адресом, который отличается от IP-адреса брандмауэра, WS-Addressing выдает вышеуказанное сообщение.Я считаю, что это очень хорошая мера безопасности, но в моем сценарии она не совсем полезна.
Цитирование стандартного представления WS-Addressing (http://www.w3.org/Submission/ws-addressing/)
«Из-за диапазона сетевых технологий, которые в настоящее время широко распространены (например, NAT, DHCP, брандмауэры), многие развертывания не могут назначить значимый глобальный URI для данной конечной точки.Чтобы позволить этим «анонимным» конечным точкам инициировать шаблоны обмена сообщениями и получать ответы, WS-адресация определяет следующий хорошо известный URI для использования с помощью конечных точек, которые не могут иметь стабильный, разрешаемый URI. http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous"
КАК мне настроить конечную точку wsHttpBinding для обращения к IP-адресу брандмауэра и игнорировать или обходить адрес, указанный в теге WS-Addressing «To» в заголовке сообщения SOAP?Или мне нужно что-то изменить в конфигурации конечной точки службы?
Помощь и рекомендации будут высоко оценены.
Марко.
P.S.:Хотя я нахожу какое-либо решение этой проблемы, я, конечно, использую BasicHttpBinding без каких-либо проблем.
Решение
Вы можете попробовать украсить свой класс обслуживания с помощью:
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]
Другие советы
Более безопасный способ справиться с этой проблемой — установить для конечной точки ListenUri URL-адрес службы, а для адреса конечной точки — внешнюю конечную точку, куда клиенты отправляют сообщения.Таким образом, служба «доверяет» сообщениям, направленным только на этот адрес, а не просто на ЛЮБОЙ адрес.
Я не знаю о решении Митча Бейкера, никогда не пробовал.Но это предполагает изменение сгенерированного кода.Есть еще один способ обойти это.
Я предполагаю, что вы сгенерировали клиентский код с помощью svcutil.exe, задав MEX-адрес, указывающий на брандмауэр.При этом вся необходимая конфигурация добавляется в App.config (или Web.config).Однако адрес службы в конфигурации будет указывать на реальный адрес службы (так как в файле WSDL адрес службы все равно будет реальным адресом службы).
Итак, что я думаю решит эту проблему:
Сгенерируйте клиентский код, указав адрес MEX (например:http://:Port-X/service/wcfservice.svc?wsdl).Это создаст всю необходимую конфигурацию.
При вызове конструктора клиента укажите URI брандмауэра в качестве EnpointAddress и имя созданной конфигурации.Таким образом, клиент отправит сообщение так, как если бы он отправлял его сервису, но на адрес брандмауэра:
клиент = новый ServiceClient(endpointConfigName, новый System.ServiceModel.EndpointAddress("http://:Port-X/service/wcfservice.svc"));