java - http_request_headers - JAX-WS-Agregar encabezados SOAP
soap client in java (7)
Intento crear un cliente independiente para consumir algunos servicios web. Debo agregar mi nombre de usuario y contraseña al encabezado SOAP. Intenté agregar las credenciales de la siguiente manera:
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");
...
Cuando llamo a un método en el servicio obtengo la siguiente excepción:
com.ibm.wsspi.wssecurity.SoapSecurityException: WSEC5048E: One of "SOAP Header" elements required.
¿Qué estoy haciendo mal? ¿Cómo agregaría estas propiedades al encabezado SOAP?
Editado: estaba usando JAX-WS 2.1 incluido en JDK6. Ahora estoy usando JAX-WS 2.2. Ahora recibo la siguiente excepción:
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.
¿Cómo hago para crear este token?
Además, si está utilizando Maven para construir su proyecto, deberá agregar la siguiente dependencia:
<dependency>
<groupId>com.sun.xml.ws</groupId>
<artifactId>jaxws-rt</artifactId>
<version>{currentversion}/version>
</dependency>
Esto le proporciona la clase com.sun.xml.ws.developer.WSBindingProvider
.
Enlace: https://mvnrepository.com/artifact/com.sun.xml.ws/jaxws-rt
En 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);
Por lo tanto, Map<String, List<String>>
de requestContext con la clave MessageContext.HTTP_REQUEST_HEADERS
se copiará a los encabezados de SOAP. Ejemplo de autenticación de aplicación con JAX-WS a través de encabezados
BindingProvider.USERNAME_PROPERTY
claves BindingProvider.USERNAME_PROPERTY
y BindingProvider.PASSWORD_PROPERTY
se procesan de manera especial en HttpTransportPipe.addBasicAuth()
, agregando Authorization
encabezado de Authorization
autorización básica estándar.
Véase también Contexto del mensaje en JAX-WS
Estoy agregando esta respuesta porque ninguno de los otros funcionó para mí.
Tuve que agregar un controlador de encabezado al proxy :
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) {
//
}
}
En el proxy, solo agrego el controlador:
BindingProvider bp =(BindingProvider)basicHttpBindingAuthentication;
bp.getBinding().getHandlerChain().add(new SOAPHeaderHandler(authenticatedToken));
bp.getBinding().getHandlerChain().add(new SOAPLoggingHandler());
No estoy 100% seguro ya que a la pregunta le faltan algunos detalles, pero si usa JAX-WS RI, eche un vistazo a Agregar encabezados SOAP al enviar solicitudes :
La forma portátil de hacer esto es crear un
SOAPHandler
y desordenar con SAAJ, pero el RI proporciona una mejor manera de hacerlo.Cuando crea un proxy o un objeto de envío, implementa la interfaz
BindingProvider
. Cuando utiliza el JAX-WS RI, puedeWSBindingProvider
aWSBindingProvider
que define algunos métodos más que solo proporciona el JAX-WS RI.Esta interfaz le permite establecer un número arbitrario de objetos de encabezado, cada uno representando un encabezado SOAP. Puede implementarlo por su cuenta si lo desea, pero lo más probable es que utilice uno de los métodos de fábrica definidos en la clase
Headers
para crear uno.
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) );
Actualice su código en consecuencia y vuelva a intentarlo. Y si no está utilizando JAX-WS RI, actualice su pregunta y proporcione más información de contexto.
Actualización: parece que el servicio web al que desea llamar está protegido con WS-Security / UsernameTokens. Esto es un poco diferente de tu pregunta inicial. De todos modos, para configurar a su cliente para que envíe nombres de usuario y contraseñas, le sugiero que compruebe la excelente publicación Implementación del perfil WS-Security UsernameToken Profile para servicios web basados en Metro (vaya al paso 4). Usar NetBeans para este paso puede facilitar mucho las cosas.
Perdón por mi mal ingles. Los datos se pueden transferir en el encabezado SOAP (JaxWS) usando @WebParam (header = true) como ese:
@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);
Si desea generar un cliente con Encabezados SOAP, necesita usar -XHastadores adicionales como ese:
wsimport -keep -Xnocompile -XadditionalHeaders -Xdebug http://12.34.56.78:8080/TestHeaders/somewsdl?wsdl -d /home/evgeny/DEVELOPMENT/JAVA/gen
Si no necesita @Oneway web service, puede usar Holder así:
@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);
Usa maven y el plugin jaxws-maven-plugin . esto generará un cliente de servicio web. Asegúrese de establecer las xadditionalHeaders en verdadero. Esto generará métodos con entradas de encabezado.
puede agregar el nombre de usuario y la contraseña al encabezado 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);