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.
как мне создать этот токен?
8 ответов
не 100% уверен, так как вопрос отсутствует некоторые детали, но если вы используете JAX-WS RI, то посмотрите на добавление заголовков SOAP при отправке запросов:
портативный способ сделать это заключается в том, что вы создаете
SOAPHandler
и беспорядок с SAAJ, но RI обеспечивает лучший способ сделать это.при создании прокси-сервера или отправки объект, они реализуют
BindingProvider
интерфейс. Когда вы используйте JAX-WS RI, вы можетеWSBindingProvider
, который определяет еще несколько методов, предоставляемых только В JAX-WS В РИ.этот интерфейс позволяет установить произвольное число объектов заголовка, каждый из них представляет заголовок SOAP. Вы может реализовать его самостоятельно, если вы хотите, но, скорее всего, вы бы использовали один из заводские методы, определенные на
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. Это немного отличается от вашего первоначального вопроса. В любом случае, чтобы настроить ваш клиент для отправки имен пользователей и паролей, я предлагаю проверить Великий пост реализация профиля WS-Security UsernameToken для веб-служб на базе Metro (переход к шагу 4). Использование NetBeans для этого шага может облегчить много.
извините за мой плохой английский. Данные могут быть переданы в заголовке 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 веб-служба, Вы можете использовать держатель, как это:
@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);
кроме того, если вы используете 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
используйте maven и плагин jaxws-maven-plugin. это создаст клиент веб-службы. Убедитесь, что вы устанавливаете xadditionalHeaders в true. Это создаст методы с входными данными заголовка.
Я добавляю этот ответ, потому что никто из них не работал для меня.
мне пришлось добавить Заголовок Обработчика до Прокси:
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());
вы можете добавить имя пользователя и пароль в заголовок 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);
на 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()
, добавление стандартной базовой авторизации .
см. также контекст сообщения в JAX-WS
я боролся со всеми ответами здесь, начиная с Паскаль!--5-->, что становится все труднее с компилятором Java, не привязанным к rt.jar
по умолчанию больше (и использование внутренних классов делает его специфичным для этой реализации среды выполнения).
ответ от edubriguenti приблизил меня. То, как обработчик подключен к последнему биту кода, не сработало для меня, хотя - он никогда не вызывался.
Я закончил использование вариация его класса обработчика, но подключенная к javax.xml.ws.Service
например такой:
Service service = Service.create(url, qname);
service.setHandlerResolver(
portInfo -> Collections.singletonList(new SOAPHeaderHandler(handlerArgs))
);