Подтвердить что ты не робот

JAX-WS - Добавление заголовков SOAP

Я пытаюсь создать отдельного клиента для использования некоторых веб-сервисов. Я должен добавить свое имя пользователя и пароль в заголовок SOAP. Я попробовал добавить учетные данные следующим образом:

OTSWebSvcsService service = new OTSWebSvcsService();
OTSWebSvcs port = service.getOTSWebSvcs();

BindingProvider prov = (BindingProvider)port;
prov.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "myusername");
prov.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "mypassword");

...

Когда я вызываю метод в службе, я получаю следующее исключение:

com.ibm.wsspi.wssecurity.SoapSecurityException: WSEC5048E: One of "SOAP Header" elements required.

Что я делаю неправильно? Как добавить эти свойства в заголовок SOAP?

Отредактировано: Я использовал JAX-WS 2.1, включенный в JDK6. Теперь я использую JAX-WS 2.2. Теперь я получаю следующее исключение:

com.ibm.wsspi.wssecurity.SoapSecurityException: WSEC5509E: A security token whose type is [http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken] is required.

Как мне создать этот токен?

4b9b3361

Ответ 1

Не 100% уверены, что в вопросе отсутствуют некоторые детали, но если вы используете JAX-WS RI, то посмотрите Добавление заголовков SOAP при отправке запросов:

Портативный способ сделать это состоит в том, что вы создаете SOAPHandler и беспорядок с SAAJ, но RI обеспечивает лучший способ сделать это.

При создании прокси-сервера или отправки объекта, они реализуют BindingProvider. Когда ты используйте JAX-WS RI, вы можете WSBindingProvider, который определяет еще несколько методов, предоставляемых только JAX-WS RI.

Этот интерфейс позволяет вам установить произвольное количество объектов заголовка, каждый из которых представляет собой заголовок SOAP. Вы может реализовать его самостоятельно, если вы но, скорее всего, вы воспользуетесь одним из методы factory, определенные на Headers для его создания.

import com.sun.xml.ws.developer.WSBindingProvider;

HelloPort port = helloService.getHelloPort();  // or something like that...
WSBindingProvider bp = (WSBindingProvider)port;

bp.setOutboundHeader(
  // simple string value as a header, like <simpleHeader>stringValue</simpleHeader>
  Headers.create(new QName("simpleHeader"),"stringValue"),
  // create a header from JAXB object
  Headers.create(jaxbContext,myJaxbObject)
);

Обновите свой код и повторите попытку. И если вы не используете JAX-WS RI, обновите свой вопрос и предоставите больше информации о контенте.

Обновление: Похоже, что веб-служба, которую вы хотите вызвать, защищена WS-Security/UsernameTokens. Это немного отличается от вашего первоначального вопроса. В любом случае, чтобы настроить клиента для отправки имен пользователей и паролей, я предлагаю проверить отличный пост Внедрение профиля UserToken WS-Security для веб-служб на основе Metro (перейти к шагу 4). Использование NetBeans для этого шага может значительно облегчить работу.

Ответ 2

Извините за мой плохой английский. Данные могут передаваться в заголовке SOAP (JaxWS) с помощью @WebParam (header = true):

@WebMethod(operationName = "SendRequest", action = "http://abcd.ru/")
@Oneway
public void sendRequest(
    @WebParam(name = "Message", targetNamespace = "http://abcd.ru/", partName = "Message")
    Data message,
    @WebParam(name = "ServiceHeader", targetNamespace = "http://abcd.ru/", header = true, partName = "ServiceHeader")
    Header serviceHeader);

Если вы хотите сгенерировать клиент с заголовками SOAP, вам нужно использовать -XadditionalHeaders:

wsimport -keep -Xnocompile -XadditionalHeaders -Xdebug http://12.34.56.78:8080/TestHeaders/somewsdl?wsdl -d /home/evgeny/DEVELOPMENT/JAVA/gen

Если вам не нужен веб-сервис @Oneway, вы можете использовать Holder следующим образом:

@WebMethod(operationName = "SendRequest", action = "http://abcd.ru/")
public void sendRequest(
    @WebParam(name = "Message", targetNamespace = "http://abcd.ru/", partName = "Message")
    Data message,
    @WebParam(name = "ServiceHeader", targetNamespace = "http://abcd.ru/", header = true, partName = "ServiceHeader")
    Holder<Header> serviceHeader);

Ответ 3

Кроме того, если вы используете Maven для создания своего проекта, вам нужно добавить следующую зависимость:

    <dependency>
        <groupId>com.sun.xml.ws</groupId>
        <artifactId>jaxws-rt</artifactId>
        <version>{currentversion}/version>
    </dependency>

Это дает вам класс com.sun.xml.ws.developer.WSBindingProvider.

Ссылка: https://mvnrepository.com/artifact/com.sun.xml.ws/jaxws-rt

Ответ 4

Используйте maven и плагин jaxws-maven-plugin. это создаст клиент веб-службы. Убедитесь, что для параметра xadditionalHeaders установлено значение true. Это создаст методы с вводом заголовков.

Ответ 5

Я добавляю этот ответ, потому что никто из других не работал у меня.

Мне пришлось добавить обработчик заголовка в Прокси:

import java.util.Set;
import java.util.TreeSet;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPHeader;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

public class SOAPHeaderHandler implements SOAPHandler<SOAPMessageContext> {

    private final String authenticatedToken;

    public SOAPHeaderHandler(String authenticatedToken) {
        this.authenticatedToken = authenticatedToken;
    }

    public boolean handleMessage(SOAPMessageContext context) {
        Boolean outboundProperty =
                (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
        if (outboundProperty.booleanValue()) {
            try {
                SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope();
                SOAPFactory factory = SOAPFactory.newInstance();
                String prefix = "urn";
                String uri = "urn:xxxx";
                SOAPElement securityElem =
                        factory.createElement("Element", prefix, uri);
                SOAPElement tokenElem =
                        factory.createElement("Element2", prefix, uri);
                tokenElem.addTextNode(authenticatedToken);
                securityElem.addChildElement(tokenElem);
                SOAPHeader header = envelope.addHeader();
                header.addChildElement(securityElem);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            // inbound
        }
        return true;
    }

    public Set<QName> getHeaders() {
        return new TreeSet();
    }

    public boolean handleFault(SOAPMessageContext context) {
        return false;
    }

    public void close(MessageContext context) {
        //
    }
}

В прокси я просто добавляю обработчик:

BindingProvider bp =(BindingProvider)basicHttpBindingAuthentication;
bp.getBinding().getHandlerChain().add(new SOAPHeaderHandler(authenticatedToken));
bp.getBinding().getHandlerChain().add(new SOAPLoggingHandler());

Ответ 6

В jaxws-rt-2.2.10-ources.jar!\com\sun\xml\ws\transport\http\client\HttpTransportPipe.java:

public Packet process(Packet request) {
        Map<String, List<String>> userHeaders = (Map<String, List<String>>) request.invocationProperties.get(MessageContext.HTTP_REQUEST_HEADERS);
        if (userHeaders != null) {
            reqHeaders.putAll(userHeaders);

Итак, Map<String, List<String>> из requestContext с ключом MessageContext.HTTP_REQUEST_HEADERS будет скопирован в заголовки SOAP. Образец Идентификация приложения с помощью JAX-WS через заголовки

BindingProvider.USERNAME_PROPERTY и BindingProvider.PASSWORD_PROPERTY обрабатываются особым образом в HttpTransportPipe.addBasicAuth(), добавляя заголовок стандартной базовой авторизации Authorization.

См. также Контекст сообщений в JAX-WS

Ответ 7

вы можете добавить имя пользователя и пароль в заголовок SOAP

BindingProvider prov = (BindingProvider)port;
prov.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
                "your end point"));
Map<String, List<String>> headers = new HashMap<String, List<String>>();
prov.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "myusername");
prov.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "mypassword");
prov.getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, headers);