Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Sécuriser ses Webservices avec Apache CXF et Wss4j
Un billet de blog de Schnuffel

Le , par Schnuffel

0PARTAGES

Bonjour,

Si vous aussi vous luttez pour créer des Webservices sécurisés, voici quelques astuces que j'ai découvertes au fur et à mesures de mes pérégrinations. Je mettrai à jour ce billet dès que je découvre de nouveaux trucs. À ce jour, je ne parle que de la partie client.

J'utilise ici Apache CXF 3.0.4 et Spring 3.1.13.RELEASE.

Mon objectif est de parvenir à tout configurer via la applicationContext.xml (à en coder le moins possible !).

D'abord, ce qu'il faut comprendre, c'est que Apache CXF utilise des intercepteurs afin de sécuriser les Webservices.

Qu'est-ce qu'un intercepteur ? Il s'agit d'un processus qui va récupérer une requête que l'on souhaite envoyer et réaliser une action dessus.

Cette action peut être soit de rajouter/supprimer/modifier des éléments de la requête, soit de la logger, etc.

Comment rajouter des intercepteurs ?
Il suffit de rajouter les classes d'intercepteur dans les listes d'intercepteurs de requêtes entrantes (inInterceptor) ou sortantes (outInterceptor)
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
		<property name="serviceClass" value="serviceType" />
		<property name="address"
			value="http://adresse" />
		<property name="inInterceptors">
			<list>
				<ref bean="logIn" />
				<ref bean="signResponse" />
			</list>
		</property>
		<property name="outInterceptors">
			<list>
				<ref bean="logOut" />
				<ref bean="saajOut" />
				<ref bean="signRequest" />
			</list>
		</property>
	</bean>
Et donc, pour sécuriser le Webservices, il faut ajouter un intercepteur qui va rajouter le header de sécurité. Voici un exemple :
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<bean id="signRequest" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
		<constructor-arg>
			<map>
				<entry key="action" value="UsernameToken Timestamp Signature Encrypt" />
				<entry key="user" value="laurent" />
				<entry key="passwordType" value="PasswordText" />
				<entry key="signatureUser" value="serverwsalias" />
				<entry key="encryptionUser" value="serverwsalias" />
				<entry key="passwordCallbackClass" value="main.ClientPasswordCallback" />
				<entry key="signaturePropFile" value="/crypt.properties"></entry>
				<entry key="signatureParts"
					value="{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;Body" />
				<entry key="encryptionPropFile" value="/crypt.properties"></entry>
				<entry key="encryptionParts"
					value="{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}UsernameToken;Body" />
			</map>
		</constructor-arg>
	</bean>
Ici, on utilise un intercepteur qui nous est fournis par CXF et qui utilise WSS4J.

Dans les actions, on définit les différentes actions que devra réaliser l'intercepteur. Ici, on a UsernameToken (authentification par username/mot de passe), Timestamp (la date de création et d'expiration de la requête va être indiquée), Signature (on va signer le message afin d'assurer l'identité de l’émetteur) et Encrypt (on va crypter la requête).
L'ordre a une importance ! les actions a b c d seront dans la requêtes sous la forme
Code : Sélectionner tout
1
2
3
4
5
6
<header>
    <d>…</d>
    <c>…</c>
    <b>…</b>
    <a>…</a>
</header>
Remarques en vrac :
- Si "signatureUser" n'est pas spécifier, il utilisera la valeur de "user"
- pour "passwordCallbackClass", on doit créer une classe qui implémente la classe CallbackHandler afin de donner un mode passe pour un user donné. CXF s'occupe ensuite de comparer.
- Pour "signatureParts" et "encryptionParts", il faut spécifier les différents éléments de la requêtes XML qui seront signés ou crypter, séparé par un ";". Il se construise de la façon suivante : {Element}{adresse du xsd qui définit l'attribut XML}Id_de_l'attribut.

Voilà, j'espère que ça pourra aider certaines personnes.

Une erreur dans cette actualité ? Signalez-le nous !