Вопрос

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

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

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

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

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

Это было полезно?

Решение 2

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

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

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

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

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

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

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

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

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

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

На стороне клиента вам нужно будет использовать Вал чтобы добавить необходимые заголовки 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, отредактируйте свой вопрос, и я постараюсь ответить.

@Майк

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top