2010-02-24 28 views
27

Estoy intentando crear un cliente independiente para consumir algunos servicios web. Debo agregar mi nombre de usuario y contraseña al encabezado SOAP. He intentado añadir las credenciales de la siguiente manera:JAX-WS - Agregar encabezados 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"); 

... 

Cuando llamo a un método en el servicio que da 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?

+0

Lo pila ws está usando? –

+0

JAX-WS 2.1 incluido en JDK6. –

Respuesta

25

No es 100% seguro de que la pregunta le faltan algunos detalles, pero si está utilizando JAX-WS RI, a continuación, echar un vistazo a Adding SOAP headers when sending requests:

La manera portátil de hacer esto es que se crea una SOAPHandler y lío con SAAJ, pero el RI proporciona una forma mejor de hacerlo de .

Cuando crea un proxy o envía el objeto , implementan la interfaz BindingProvider. Cuando utiliza el JAX-WS RI, puede abatir a WSBindingProvider, que define algunos métodos más provistos solo por JAX-WS RI.

Esta interfaz le permite establecer un número arbitrario de objeto de encabezado, cada uno que representa un encabezado SOAP. Usted puede implementarlo por su cuenta si desea , pero lo más probable es que utilice uno de los métodos de fábrica definidos en 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) 
); 

actualizar el código en consecuencia y vuelve 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 que desea llamar está protegido con WS-Security/UsernameTokens. Esto es un poco diferente de tu pregunta inicial. De todos modos, para configurar su cliente para que envíe nombres de usuario y contraseñas, le sugiero que compruebe la gran publicación Implementing the WS-Security UsernameToken Profile for Metro-based web services (salte al paso 4). Usar NetBeans para este paso puede facilitar mucho las cosas.

+1

No puedo obtener eclipse para importar esta clase 'com.sun.xml.internal.ws.developer.WSBindingProvider'. – pihentagy

+0

¿Habrá algún problema de portabilidad si usamos las clases del paquete com.sum? – james2611nov

7

Además, si usted está utilizando Maven para construir su proyecto, tendrá que añadir 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

24

Lo siento por mi mala Inglés.Los datos pueden transferirse en el encabezado SOAP (jaxws) mediante el uso de @WebParam (cabecera = true) así:

@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 Usted desea generar cliente con encabezados SOAP, necesita utilizar -XadditionalHeaders así:

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

Si no necesita @Oneway servicio web, puede utilizar titular 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); 
+1

+1, '' XadditionalHeaders' es un atributo importante en este caso. –

+0

header = true hizo el truco para mí. Hice una copia del talón existente y configuré el encabezado = verdadero en la copia para que maven wsimport no sobrescriba los talones generados. – Zeus

+0

¿Cuál es el equivalente en maven plugin para -additionalHeader? –

2

use experto y el plugin jaxws-maven-plugin. esto generará un cliente de servicio web. Asegúrese de establecer el valor xadditionalHeaders en verdadero. Esto generará métodos con entradas de encabezado.

0

Agregué esta respuesta porque ninguno de los otros funcionó para mí.

he tenido que añadir un Cabecera Handler a la 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, acabo de agregar el controlador:

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

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); 

Entonces, Map<String, List<String>> from requestContext with key MessageContext.HTTP_REQUEST_HEADERS se copiará a los encabezados de SOAP. Muestra de Application Authentication with JAX-WS via headers

BindingProvider.USERNAME_PROPERTY y BindingProvider.PASSWORD_PROPERTY teclas se procesan de manera especial en HttpTransportPipe.addBasicAuth(), añadiendo autorización básica estándar Authorization cabecera.

Ver también Message Context in JAX-WS

0

puede agregar el nombre de usuario y contraseña a la cabecera de 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); 
Cuestiones relacionadas