3 votes

Comment ajouter un Soap Header défini dans un wsdl à un client de service web dans CXF ?

J'ai un wsdl qui définit un en-tête soap qui doit être passé lors de l'appel du service web.

L'exemple d'en-tête SOAP est le suivant :

<soapenv:Header>
   <AuthenticationInfo>
      <userName>User</userName>
      <password/>
   </AuthenticationInfo>
</soapenv:Header>

Le wsdl2java de CXF a généré une classe java "AuthenticationInfo" que je peux créer et remplir avec un nom d'utilisateur et un mot de passe, mais je ne sais pas comment transmettre ces informations au client CXF lorsqu'il appelle le service web.

12voto

En générant la classe de proxy à l'aide de Apache CXF, l'ajout de extendedSoapHeaders avec true générera la classe PortType avec les arguments Request et Header.

<wsdlOption>              
<wsdl>${project.basedir}/src/main/resources/wsdl/sample.wsdl</wsdl>
 <!-- enables processing of implicit SOAP headers, default is false -->
<extendedSoapHeaders>true</extendedSoapHeaders>
</wsdlOption>

4voto

Afrin Points 577

La manière la plus simple de le faire serait de créer un fichier ArrayList de Header et ajoutez tous vos paramètres ou un Map<String,Object> et ajoutez tous vos en-têtes comme map.put("param1",param1).

Enfin, récupérez votre contexte de demande et ajoutez cette liste de tableaux de cartes en tant que

requestContext.put(MessageContext.HTTP_REQUEST_HEADERS,
soapHeaders); 

Si vous essayez de passer des en-têtes de savon personnalisés, référez-vous à CE LIEN .

Les pièges généraux ont été mentionnés dans CETTE DISCUSSION . Cela pourrait vous être utile.

2voto

Alex Points 3448

Je me suis retrouvé dans la même situation : wsdl2java a généré la classe d'en-tête, et j'avais besoin de l'ajouter comme en-tête SOAP à la demande SOAP sortante.

Ma solution en code était la suivante (en réutilisant la question originale) AuthenticationInfo comme nom de classe de l'en-tête) :

import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.headers.Header;

AuthenticationInfo ai = new AuthenticationInfo();
ai.setUserName("User");
ai.setPassword("");

List<Header> soapHeaders = new ArrayList<Header>();

Header h1 = new Header(new QName("http://namespace/of/AuthenticationInfo", "AuthenticationInfo"), 
                       ai, new JAXBDataBinding(AuthenticationInfo.class));

soapHeaders.add(h1);

ClientProxy.getClient(port).getRequestContext().put(Header.HEADER_LIST, soapHeaders);

1voto

CodeNotFound Points 720

Si l'en-tête SOAP est défini dans le WSDL, il peut alors être spécifié implicite ou explicite .

CXF fournit le Outil wsdl2java pour générer une interface de service Java à partir d'un WSDL. Dans le cas d'en-têtes explicites, les en-têtes SOAP sont automatiquement détectés et mis à disposition dans le cadre de l'interface de service générée.

Si les en-têtes SOAP ont été définis de manière implicite, vous devez activer l'option -exsh qui déclenche le traitement des en-têtes SOAP implicites. Là encore, les en-têtes SOAP seront disponibles dans le cadre de l'interface Java du service qui sera générée. Si vous voulez un exemple concret, vous pouvez consulter un article de blog que j'ai fait sur comment ajouter un en-tête de savon cxf .

Notez que CXF supporte également autres moyens d'ajouter des en-têtes SOAP .

0voto

Massimo Da Ros Points 161

Avec CXF 3.4.4

vous pouvez ajouter un en-tête configurant la sécurité comme ceci

<soapenv:Header>
    <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/07/secext">
    <wsse:UsernameToken xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility">
    <wsse:Username>MY-USER</wsse:Username>
    <wsse:Password Type="wsse:PasswordText">MY-PWD</wsse:Password>
        </wsse:UsernameToken>
    </wsse:Security>
</soapenv:Header>

En utilisant un intercepteur, comme décrit ici : http://cxf.apache.org/docs/ws-security.html

Client serviceClient = ClientProxy.getClient ( port );

Endpoint cxfEndpoint = serviceClient.getEndpoint ();

Map<String, Object> outProps = new HashMap<> ();
outProps.put ( WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN );
outProps.put ( WSHandlerConstants.USER, "MY-USER" );
outProps.put ( WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT );
outProps.put ( WSHandlerConstants.PW_CALLBACK_CLASS, ClientPasswordCallback.class.getName () ); 

WSS4JOutInterceptor requestInterceptor = new WSS4JOutInterceptor ( outProps );
cxfEndpoint.getOutInterceptors ().add ( requestInterceptor );

MyRequest request = new MyRequest ();

Object [] res = serviceClient.invoke ( "operation-name", request );
MyResponse out = ( MyResponse ) res [0];

Où "operation-name" est le nom de l'opération WebService à invoquer

Le WSPasswordCallback est :

import org.apache.wss4j.common.ext.WSPasswordCallback;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import java.io.IOException;

public class ClientPasswordCallback implements CallbackHandler {

    public void handle ( Callback [] callbacks ) throws IOException, UnsupportedCallbackException {

        WSPasswordCallback passwordCallback = ( WSPasswordCallback ) callbacks [0];

        // Set the password for our message.
        passwordCallback.setPassword ( "MY-PWD" );
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X