2010-02-24 9 views
27

J'essaie de créer un client autonome pour consommer certains services Web. Je dois ajouter mon nom d'utilisateur et mot de passe à l'en-tête SOAP. J'ai essayé d'ajouter les informations d'identification comme suit:JAX-WS - Ajout d'en-têtes 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"); 

... 

Quand j'appelle une méthode sur le service que je reçois l'exception suivante:

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

Qu'est-ce que je fais mal? Comment ajouter ces propriétés à l'en-tête SOAP? Edité: J'utilisais JAX-WS 2.1 inclus dans JDK6. J'utilise maintenant JAX-WS 2.2. Je reçois maintenant l'exception suivante:

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. 

Comment puis-je créer ce jeton?

+0

Quelle pile ws utilisez-vous? –

+0

JAX-WS 2.1 inclus dans JDK6. –

Répondre

25

pas 100% sûr que la question manque certains détails, mais si vous utilisez JAX-WS RI, ont alors un oeil à Adding SOAP headers when sending requests:

La manière portable de faire est que vous créez un SOAPHandler et gâcher avec SAAJ, mais le RI fournit un meilleur moyen de le faire. Lorsque vous créez un proxy ou envoyez l'objet , ils implémentent l'interface BindingProvider. Lorsque vous utiliser le JAX-WS RI, vous pouvez downcast à WSBindingProvider qui définit un quelques méthodes supplémentaires fournies uniquement par le JAX-WS RI.

Cette interface vous permet de définir un nombre arbitraire d'objet en-tête, , chacun représentant un en-tête SOAP. Vous pouvez l'implémenter sur votre propre si vous voulez, mais vous utiliserez probablement l'une des les méthodes d'usine définies sur la classe Headers pour en créer un.

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

Mettez à jour votre code en conséquence et essayer à nouveau. Et si vous n'utilisez pas JAX-WS RI, veuillez mettre à jour votre question et fournir plus d'informations contextuelles.

Mise à jour: Il semble que le service Web que vous souhaitez appeler soit sécurisé avec WS-Security/UsernameTokens. C'est un peu différent de votre question initiale. Quoi qu'il en soit, pour configurer votre client pour qu'il envoie des noms d'utilisateur et des mots de passe, je vous suggère de vérifier le bon post Implementing the WS-Security UsernameToken Profile for Metro-based web services (passez à l'étape 4). Utiliser NetBeans pour cette étape pourrait grandement faciliter les choses.

+1

Je n'arrive pas à obtenir eclipse pour importer cette classe 'com.sun.xml.internal.ws.developer.WSBindingProvider'. – pihentagy

+0

Y aura-t-il des problèmes de portabilité si nous utilisons les classes du paquet com.sum? – james2611nov

7

De plus, si vous utilisez Maven pour construire votre projet, vous aurez besoin d'ajouter la dépendance suivante:

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

Cela vous fournit la classe com.sun.xml.ws.developer.WSBindingProvider.

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

24

Désolé pour mon mauvais anglais.Les données peuvent être transférées en-tête SOAP (JAXWS) en utilisant @WebParam (tête = true) comme ça:

@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 vous voulez générer client avec en-têtes SOAP, besoin d'utiliser -XadditionalHeaders comme ça:

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

Si vous ne devez pas @Oneway service Web, vous pouvez utiliser des supports comme ça:

@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, le '-XadditionalHeaders' est un attribut important dans ce cas. –

+0

header = true a fait l'affaire pour moi. Je devais faire une copie du talon existant et mettre l'en-tête = true sur la copie pour le wavimport de maven de ne pas écraser les talons générés. – Zeus

+0

Quel est l'équivalent dans le plugin maven pour -additionalHeader? –

2

Maven et le plug-in jaxws-maven-plugin. Cela générera un client de service Web. Assurez-vous de définir le xadditionalHeaders sur true. Cela générera des méthodes avec des entrées d'en-tête.

0

J'ajoute cette réponse car aucun des autres n'a fonctionné pour moi.

je dû ajouter un tête Gestionnaire au 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) { 
     // 
    } 
} 

Dans le proxy, je viens d'ajouter le gestionnaire:

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

Ainsi, Map<String, List<String>> from requestContext avec la clé MessageContext.HTTP_REQUEST_HEADERS sera copiée dans les en-têtes SOAP. clés Exemple de Application Authentication with JAX-WS via headers

BindingProvider.USERNAME_PROPERTY et BindingProvider.PASSWORD_PROPERTY sont traités de façon particulière dans HttpTransportPipe.addBasicAuth(), en ajoutant en-tête d'autorisation standard de base Authorization.

Voir aussi Message Context in JAX-WS

0

vous pouvez ajouter le nom d'utilisateur et mot de passe à l'en-tête 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);