Вызов веб-службы .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 для генерации клиента.

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

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

19.08.2008 15:54:59
WSE устарела и должна использоваться только в том случае, если нет других вариантов.
John Saunders 4.09.2009 20:51:55
@Michael: чувак, я чувствую твою боль (так как мой поиск по HOWTO привел меня сюда).
Roboprog 3.02.2010 02:52:23
5 ОТВЕТОВ

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

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

0
19.08.2008 16:06:09
2
19.08.2008 16:19:51

@Майк

Я недавно сделал тест, и это код, который я использовал. Я не использую политики, но я использовал 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();
        }
    }
}
3
19.08.2008 21:18:27

Спецификации 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, отредактируйте ваш вопрос, и я постараюсь ответить изо всех сил.

10
17.09.2008 14:57:02
РЕШЕНИЕ

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

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

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

Итак, шаги, которые мы должны были сделать, в двух словах:

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

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

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

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

10
2.04.2009 20:37:14
Эта проблема с ws-решением - настоящая боль в заднице. WSS2 не только использует старую предварительную версию WS-Addressing, но и добавляет элементы propritery в мыльный заголовок (например, wsa: via), которые не являются частью схемы. Что за черепок
skaffman 1.07.2009 16:00:17
Каждый должен помнить, что WSE устарела. Это было временное решение, позволяющее веб-сервисам .NET использовать появляющийся стек WS- *. Это не должно удивлять, если оно не поддерживает окончательные стандарты. WCF делает поддержку окончательные стандартные версии WS- * протоколов. Он заменил WSE и должен использоваться для всех новых разработок. Код WSE должен быть заменен как можно скорее.
John Saunders 1.09.2009 02:31:28
@John: люди, реализующие клиента, не имеют большого выбора того, что поставщик использовал для реализации сервера. Я вижу, вы зарабатываете на жизнь этим, но разработчикам, которые должны интегрироваться с этим, действительно ужасно, что он настолько зависит от наличия только правильных инструментов только правильной версии от One True Vendor. См. 72.249.21.88/nonintersecting/…
Roboprog 3.02.2010 02:56:46
@Roboprog: Вы часто делаете есть выбор. Если сервер был создан с использованием чего-то стандартного, то используйте WCF на клиенте. Если нет, то подумайте «нет», когда финансы позволяют. В противном случае мы все еще будем иметь дело с нестандартами, такими как WSE 2.0, через десятилетие.
John Saunders 3.02.2010 04:36:16
В моем случае выбора не было: мы звонили в веб-службу, предоставленную государственным агентством.
Michael Sharek 3.02.2010 15:24:58