Фон (крошечный) :
Несколько лет назад я написал для клиента службу WCF, настроенную на использование basicHttpBinding с режимом безопасности = "Транспорт" с clientCredentialType = "Сертификат", то есть клиенты аутентифицируют себя, используя (клиентский) сертификат. Служба использует собственный AuthorizationManager, который проверяет, присутствует ли отпечаток входящего сертификата в предварительно определенном списке действительных отпечатков сертификатов. Если входящий сертификат считается действительным, операция может продолжаться (если нет, генерируется исключение).
Служба работала безупречно в течение примерно четырех лет, и все были счастливы. Однако, как это часто бывает, требования меняются, и недавно к моему клиенту обратились разработчики, желающие подключить свои приложения к сервису моего клиента. Единственная проблема заключается в том, что эти разработчики используют какой-то вариант Java в качестве предпочитаемой платформы, и теперь мы сталкиваемся с серьезными проблемами. Короче говоря, никому не удалось заставить свою реализацию Java (например, Metro, Axis2) работать со службой, так как она в настоящее время настроена.
На прошлой неделе мы попытались заставить его работать с клиентом, написанным на Java (Metro, JAX-WS), изменив привязку к wsHttpBinding с режимом безопасности = "TransportWithMessageCredential" с сообщением clientCeredentialType = "UserName". Я также добавил пользовательский UserNamePassWordValidatorType к элементу учетных данных службы в файле конфигурации.
Затем я прокомментировал пользовательский AuthorizationManager, поскольку от клиента не было получено ни одного сертификата.
Да, и вот, на этот раз мы получили как SoapUI, так и клиент Java для общения со службой.
(Кстати, наш сервис размещен в службе Windows)
Как ни крути, мы решили настроить сервис с двумя привязками: существующая базовая HTTBBinding, которая долгое время работала без сбоев, и недавно протестированная wsHttpBinding. Таким образом, у нас было бы что-то вроде:
<services>
<service name="SuperDuperService" behaviorConfiguration="superDuperBehaviour">
<endpoint binding="basicHttpBinding" contract="ISuperDuperService" bindingConfiguration="SecureTransport"/>
<endpoint binding="wsHttpBinding" address="stws" contract="ISuperDuperService" bindingConfiguration="SecureTransportAndSoap"/>
<endpoint binding="mexHttpsBinding" address="mex" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="https://<url + port>/SuperDuperService"/>
</baseAddresses>
</host>
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="SecureTransport" maxBufferSize="2065536" maxBufferPoolSize="524288" maxReceivedMessageSize="2065536">
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
<readerQuotas maxDepth="32" maxStringContentLength="6553600" maxArrayLength="2065536"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
</binding>
</basicHttpBinding>
<wsHttpBinding>
<binding name="SecureTransportAndSoap">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="superDuperBehaviour">
<serviceCredentials>
<!-- The following element specifies the certificate use by this service for HTTPS (SSL) based transport security -->
<serviceCertificate findValue="<some identifier>"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName" />
<userNameAuthentication userNamePasswordValidationMode ="Custom" customUserNamePasswordValidatorType
="SupportClasses.CustomUserNameValidator,SupportClasses"/>
</serviceCredentials>
<!-- The following element specifies how we're authorizing based on the client certificates received -->
<serviceAuthorization serviceAuthorizationManagerType="SupportClasses.AuthorizationManager, SupportClasses"/>
<serviceMetadata httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
Так в чем же проблема, которую вы можете задать? Хорошо, видите этот элемент <serviceBehavior>
? Как вы, наверное, знаете, этот элемент применяется глобально к сервису, что означает, что во время выполнения будут вызваны как CustomUserNameValidator, так и AuthorizationManager. Последний будет жаловаться на отсутствие сертификата, когда клиент вызывает сервис, используя wsHttpBinding!
Argh!
Альтернативные решения .
Пока что я предложил альтернативные решения:
Альтернатива 1) Создайте другую службу Windows, на которой размещена наша служба WCF, по другому URL-адресу. Тогда обе службы будут иметь отдельную конфигурацию.
Альтернатива 2) Создайте две реализации службы, размещенные в одной и той же службе Windows, и представьте их обе в элементе, каждая со своим собственным связыванием и serviceBehaviour
Альтернатива 3) Выясните, возможно ли вообще сохранить текущую конфигурацию и обеспечить мирное сосуществование CustomUserNameValidator и AuthorizationManager
Извините за этот длинный пост, но мне нужно было быть внимательным, предоставляя справочную информацию для моего вопроса (вопросов).
Вопрос 1) Кто-нибудь получил WCF для работы с Java-клиентами, использующими нетривиальные конфигурации?
Вопрос 2) Кто-нибудь получил предложение о том, как решить альтернативу 3? (если это вообще возможно)
Вопрос 3) Какую из перечисленных альтернатив, если таковая имеется, вы бы порекомендовали?
Вопрос 4) Есть ли другие известные вам альтернативы, о которых я не подумал?
Для справки, я посмотрел на инструмент взаимодействия WCF, но не могу понять, как он может нам помочь. Если кто-то, читающий это, имел хорошие результаты, используя "мастера" взаимодействия,
пожалуйста, дайте мне знать.
Заранее спасибо.
- norgie