[DEV] WS-Security – Username token – Client CXF

WS-Security permet de sécuriser facilement des web services. Il permet entre autre :

  • Une authentification par user/password (token) entre les services,
  • Un encryptage d’une partie ou de la totalité d’un message,
  • De signer des messages,
  • D’horodater des messages.

Apache CXF est un framework permettant d’implémenter les standards JAX-WS pour créer des web services en Java en se reposant sur WSS4J. Il s’intègre également avec Spring, Aegis, RESTful, et WS-*. Il est aujourd’hui dans sa version 2.1.1.

securityalert

Vous trouverez sur le wiki cxf un complément d’information et un exemple d’implémentation de WS-Security via CXF. Il existe également un exemple utilisant XWSSS avec Spring.

Une des sécurité la plus basique est celle fournie par l’authentification via Username Token.

Je vais donc vous présenter un moyen simple d’ajouter l’authentification via Username Token dans les en-têtes Soap Header de votre client web service en utilisant CXF.

1 – Le XML en entrée d’un web service contient l’en-tête sécurisé :

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<wsse:Security xmlns:wsse="..."
SOAP-ENV:mustUnderstand="1">
<wsse:UsernameToken xmlns:wsu="..."
wsu:Id="XWSSGID-1172860158358-935964365">
<wsse:Username>user</wsse:Username>
<wsse:Password Type="...#PasswordText">password</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<echoRequest
xmlns="...">Hello</echoRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

2 – Vous pouvez ajouter facilement cette en-tête sécurisée en Java directement dans le code du client Web Service (pouvant être généré via la commande wsdl2java de CXF/Axis).

Voici un exemple de code client :

WebService_Service service = new WebService_Service();
WebService port = service.getPort(WebService.class);

A la suite, il suffit d’ajouter un proxy client qui va prendre en charge les en-têtes (SOAP Header) sécurisées :

Client client = ClientProxy.getClient(port);
Endpoint cxfEndpoint = client.getEndpoint();

Puis instancier une HashMap qui contiendra les propriétés de sécurité :

Map outProps = new HashMap();

On ajoute ensuite l’intercepteur qui prendra en charge les propriétés définies :

WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
cxfEndpoint.getOutInterceptors().add(wssOut);
cxfEndpoint.getOutInterceptors().add(new SAAJOutInterceptor());

Et pour finir on ajoute les propriétés de sécurité (user/password) dans la HashMap :

outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
// Specify our username
outProps.put(WSHandlerConstants.USER, “ws-client”);
// Password type : plain text
//outProps.setProperty(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
// for hashed password use:
//properties.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_DIGEST);
outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_DIGEST);
// Callback used to retrive password for given user.
outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientPasswordHandler.class.getName());

Comme vous pouvez le constater, le mot de passe n’est pas défini ici. La dernière ligne (PW_CALLBACK_CLASS) intervient alors. C’est une fonction de callback qui va se charger de l’ajout du mot de passe dans l’en-tête.

Voici donc cette fonction de callback :

public class ClientPasswordHandler implements CallbackHandler {
  public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
    WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
    // set the password for the outbound message.
    pc.setPassword(”password”);
  }
}

Avec ce code, vos en-têtes seront générées automatiquement depuis vos clients (Java) web service.

1 commentaires On [DEV] WS-Security – Username token – Client CXF

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.