Как заставить клиентов WCF и Java работать. Требуется помощь специалиста - PullRequest
1 голос
/ 12 ноября 2011

Фон (крошечный) :

Несколько лет назад я написал для клиента службу 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

1 Ответ

0 голосов
/ 13 ноября 2011

Я бы начал с добавления второго элемента в // services и настроил бы его с новым атрибутом @bindingConfiguration и отдельным атрибутом @address. Я думаю, что это будет проще, чем альтернативы 1, 2 или 3; или, может быть, это вариант 3, я не могу сказать.

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

Рассматривали ли вы эту серию по WCF и взаимодействию Java ?

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

...