2010-02-24 12 views
27

Sto cercando di creare un client standalone per consumare alcuni servizi Web. Devo aggiungere il mio nome utente e password all'intestazione SOAP. Ho provato ad aggiungere le credenziali come segue:JAX-WS - Aggiunta di intestazioni 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"); 

... 

Quando chiamo un metodo sul servizio ottengo la seguente eccezione:

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

Che cosa sto facendo di sbagliato? Come aggiungerei queste proprietà all'intestazione SOAP?

Modificato: stavo usando JAX-WS 2.1 incluso in JDK6. Ora sto usando JAX-WS 2.2. Ricevo ora la seguente eccezione:

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. 

Come faccio a creare questo token?

+0

Cosa pila ws stai usando? –

+0

JAX-WS 2.1 incluso in JDK6. –

risposta

25

non al 100% sicuro come la questione manca alcuni dettagli, ma se si sta utilizzando JAX-WS RI, quindi di dare un'occhiata a Adding SOAP headers when sending requests:

Il modo portatile di questa operazione è che si crea un SOAPHandler e mess con SAAJ, ma il RI fornisce un modo migliore di fare questo .

Quando si crea un oggetto proxy o di spedizione , viene implementata l'interfaccia BindingProvider. Quando si utilizza il JAX-WS RI , è possibile eseguire il downcast su WSBindingProvider che definisce uno alcuni altri metodi forniti solo dal JAX-WS RI.

Questa interfaccia consente di impostare un numero arbitrario di oggetto Header, ognuno rappresentante un'intestazione SOAP. È possibile implementarlo da soli se si desidera utilizzare lo standard , ma molto probabilmente si utilizzerà uno dei metodi di produzione definiti nella classe Headers per crearne 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) 
); 

aggiornare il codice di conseguenza e riprova. E se non stai usando JAX-WS RI, ti preghiamo di aggiornare la tua domanda e fornire maggiori informazioni sul contesto.

Aggiornamento: Sembra che il servizio Web che si desidera chiamare sia protetto con WS-Security/UsernameTokens. Questo è un po 'diverso dalla tua domanda iniziale. Ad ogni modo, per configurare il tuo client per l'invio di nomi utente e password, ti suggerisco di controllare l'ottimo post Implementing the WS-Security UsernameToken Profile for Metro-based web services (vai al passaggio 4). L'utilizzo di NetBeans per questo passaggio potrebbe facilitare molto le cose.

+1

Non riesco a ottenere eclissi per importare questa classe 'com.sun.xml.internal.ws.developer.WSBindingProvider'. – pihentagy

+0

Ci saranno problemi di portabilità se usiamo le classi dal pacchetto com.sum? – james2611nov

7

Inoltre, se si sta usando Maven per costruire il vostro progetto, è necessario aggiungere la seguente dipendenza:

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

Questo vi dà la classe com.sun.xml.ws.developer.WSBindingProvider.

Link: https://mvnrepository.com/artifact/com.sun.xml.ws/jaxws-rt

24

Ci dispiace per il mio cattivo inglese.I dati possono essere trasferiti in SOAP intestazione (jaxws) utilizzando @WebParam (intestazione = true) così:

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

Se Volete generare cliente con intestazioni SOAP, è necessario utilizzare -XadditionalHeaders così:

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

Se non è necessario @Oneway servizio web, è possibile utilizzare Titolare del genere:

@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' è un attributo importante in questo caso. –

+0

header = true ha fatto il trucco per me. Ho fatto una copia dello stub esistente e ho impostato l'header = true sulla copia per il maven wsimport per non sovrascrivere gli stub generati. – Zeus

+0

Qual è l'equivalente nel plugin di maven per -additionalHeader? –

2

utilizzare Maven e il plugin jaxws-maven-plugin. questo genererà un client di servizio web. Assicurati di impostare xadditionalHeaders su true. Questo genererà metodi con input di intestazione.

0

Sto aggiungendo questa risposta perché nessuno degli altri ha funzionato per me.

ho dovuto aggiungere un Header Handler 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) { 
     // 
    } 
} 

nel proxy, ho solo aggiungere il gestore:

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

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

Quindi, Map<String, List<String>> da requestContext con chiave MessageContext.HTTP_REQUEST_HEADERS verrà copiato nelle intestazioni SOAP. Campione di Application Authentication with JAX-WS via headers

BindingProvider.USERNAME_PROPERTY e BindingProvider.PASSWORD_PROPERTY tasti sono trattati in modo speciale HttpTransportPipe.addBasicAuth(), aggiungendo autorizzazione standard base Authorization intestazione.

Vedi anche Message Context in JAX-WS

0

è possibile aggiungere il nome utente e la password per l'intestazione 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);