Вызов веб-службы .NET (WSE 2/3, WS-Security) из Java

Мне нужно вызвать веб-службу, написанную на .NET, из Java. Веб-служба реализует стек WS-Security (WSE 2 или WSE 3, это не ясно из имеющейся у меня информации).

Информация, которую я получил от поставщика услуг, включала WSDL, файл policyCache.config, некоторый образец кода C# и образец приложения, которое может успешно вызывать службу.

Это не так полезно, как кажется, потому что неясно, как я должен использовать эту информацию для написания клиента Java. Если запрос веб-службы не подписан в соответствии с политикой, он отклоняется службой. Я пытаюсь использовать Apache Axis2 и не могу найти никаких инструкций о том, как я должен использовать файл policyCahce.config и WSDL для создания клиента.

Есть несколько примеров, которые я нашел в Интернете, но во всех случаях авторы примеров контролировали и сервис, и клиент, и поэтому могли вносить изменения с обеих сторон, чтобы заставить его работать. Я не в таком положении.

Кто-нибудь сделал это успешно?

WSE устарела и должна использоваться только в том случае, если нет других вариантов.

John Saunders 05.09.2009 00:51

@Michael: чувак, я чувствую твою боль (поскольку мой поиск по HOWTO привел меня сюда).

Roboprog 03.02.2010 05:52
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
22
2
13 896
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

CXF - Я бы посмотрел в CXF. Я использовал его для создания веб-службы и клиента на java с помощью ws-secuirty. Я также подключил к нему веб-сервис .net.

У них тоже есть неплохая документация. Мне с ней повезло больше, чем с осью.

@Майк

Я недавно сделал тест, и это код, который я использовал. Я не использую политики, но я использовал WS-Security с аутентификацией в виде обычного текста. В CXF есть действительно хорошая документация о том, как это сделать.

Я использовал wsdl2java, а затем добавил этот код, чтобы использовать веб-службу с ws-security.

Я надеюсь, что это помогает вам.

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.handler.WSHandlerConstants;

public class ServiceTest implements CallbackHandler
{

     public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {

            WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
            // set the password for our message.
            pc.setPassword("buddah");
        }

    public static void main(String[] args){
        PatientServiceImplService locator = new PatientServiceImplService();
        PatientService service = locator.getPatientServiceImplPort();

        org.apache.cxf.endpoint.Client client = org.apache.cxf.frontend.ClientProxy.getClient(service);
        org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();

        Map<String, Object> outProps = new HashMap<String, Object>();
        outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN + " " +  WSHandlerConstants.TIMESTAMP);
        outProps.put(WSHandlerConstants.USER, "joe");
        outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);

        // Callback used to retrieve password for given user.
        outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ServiceTest.class.getName());

        WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
        cxfEndpoint.getOutInterceptors().add(wssOut);


        try
        {
            List list = service.getInpatientCensus();
            for(Patient p : list){
                System.out.println(p.getFirstName() + " " + p.getLastName());
            }

        }
        catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Спецификации WS-Security обычно не содержатся в WSDL (никогда в WSDL WSE). Таким образом, wsdl2java не знает, что WS-Security даже требуется для этой службы. Тот факт, что в WSDL WSE отсутствуют ограничения безопасности, меня сильно разочаровал (WCF будет включать информацию WS-Trust в WSDL).

На стороне клиента вам необходимо использовать Rampart для добавления необходимых заголовков WS-Security в исходящее сообщение клиента. Поскольку WSDL не сообщает, какие настройки WS-Security необходимы, лучше всего спросить у поставщика услуг, что требуется. Требования WS-Security могут представлять собой простой текстовый пароль, сертификаты X509 или зашифрованное сообщение ... Rampart должен быть в состоянии обрабатывать большинство этих сценариев.

Apache Rampart "включается" путем включения модуля в вашем файле axis2.xml. Вам нужно будет загрузить модуль Rampart и поместить его в определенное место в каталоге axis2, а затем изменить файл xml. Вы также можете использовать Rampart программно (отредактируйте исходный вопрос, если это необходимо, и я отредактирую этот ответ).

В зависимости от того, как вы настраиваете rampart (через другие файлы XML или программно), он будет перехватывать любые исходящие сообщения и добавлять в них необходимую информацию WS-Security. Я лично использовал axis2 с rampart для вызова службы WSE3, которая защищена с помощью UsernameToken в виде открытого текста, и она отлично работала. Аналогичные, но более сложные сценарии также должны работать. Более подробную информацию о том, как настроить и начать работу с Rampart, можно найти на сайте, указанном выше. Если у вас есть проблемы с особенностями Rampart или с тем, как использовать Rampart с вашей конкретной настройкой WSE, отредактируйте свой вопрос, и я постараюсь ответить.

Ответ принят как подходящий

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

Похоже, что сервисы, построенные в .NET, следуют старому стандарту ws-адресации (http://schemas.xmlsoap.org/ws/2004/03/addressing/), а axis2 понимает только новый стандарт (http://schemas.xmlsoap.org/ws/2004/08/addressing/).

Кроме того, предоставленный файл policyCache.config имеет форму, которую модуль rampart оси 2 не может понять.

Итак, вкратце, что нам нужно было сделать:

  • Прочтите policyCache.config и попытайтесь понять его. Затем перепишите его в политику, которую сможет понять вал. (Помог какой-то обновленные документы.)
  • Настройте вал с помощью этой политики.
  • Возьмите ключи, которые были предоставлены в файле .pfx, и преобразуйте их в хранилище ключей Java. В комплекте с Jetty есть утилита, которая может это сделать.
  • Настройте вал с этим хранилищем ключей.
  • Напишите собственный обработчик axis2, преобразующий в обратном направлении новые данные ws-адресации, поступающие из axis2, в более старые данные, ожидаемые службой.
  • Настройте axis2 для использования обработчика исходящих сообщений.

В конце концов, это было много конфигурации и кода для чего-то, что должно было быть открытым стандартом, поддерживаемым поставщиками.

Хотя я не уверен, что есть альтернатива ... можете ли вы подождать, пока поставщики (или, в данном случае, один поставщик) убедятся, что все будет взаимодействовать?

В качестве постскриптума я добавлю, что не я закончил работу, это был кто-то другой из моей команды, но я думаю, что я правильно понял основные детали. Другой вариант, который я рассматривал (до того, как меня взял на себя мой товарищ по команде), состоял в том, чтобы напрямую вызвать WSS4J API для создания конверта SOAP, как того ожидала служба .NET. Думаю, это тоже сработало бы.

Эта проблема с ws-адресацией - настоящая заноза в заднице. WSS2 не только использует старую предварительную версию WS-Addressing, но и добавляет в заголовок мыла элементы propritery (например, wsa: via), которые не являются частью схемы. Что за черепок.

skaffman 01.07.2009 20:00

Всем следует помнить, что WSE устарела. Это было временное решение, позволяющее веб-службам .NET использовать развивающийся стек WS- *. Не должно быть ничего удивительного, если он не поддерживает окончательные стандарты. WCF делает поддерживает последние стандартные версии протоколов WS- *. Он заменил WSE и должен использоваться для всех новых разработок. Код WSE следует заменить как можно скорее.

John Saunders 01.09.2009 06:31

@John: люди, реализующие клиент, не имеют особого выбора, что поставщик использовал для реализации сервера. Я вижу, что вы зарабатываете себе на жизнь, занимаясь этим, но для разработчиков, которым необходимо интегрироваться с этим, действительно отстой, что так зависит от наличия только нужных инструментов только нужной версии от One True Vendor. См. 72.249.21.88/nonintersecting/…

Roboprog 03.02.2010 05:56

@Roboprog: у делать часто есть выбор. Если сервер был создан с использованием чего-то стандартного, используйте WCF на клиенте. Если нет, то подумайте о том, чтобы сказать «нет», когда позволяют финансы. В противном случае через десять лет мы все еще будем иметь дело с нестандартными решениями, такими как WSE 2.0.

John Saunders 03.02.2010 07:36

В моем случае выбора не было: мы звонили в веб-службу, предоставляемую государственным агентством.

Michael Sharek 03.02.2010 18:24

@MichaelSharek У вас нет проекта для просмотра? Я много боролся с этим пару дней, но безуспешно. Получение Подпись или дешифрование было недопустимым с сервера.

Marcus 05.09.2012 11:33

Привет, Маркус - это было четыре года назад. Я обыскал свой ноутбук, но у меня больше нет файлов. :(

Michael Sharek 09.09.2012 07:17

Другие вопросы по теме