JAX-*S: Handlers & Filters

L'objectif de ce TP est de mettre en place des intercepteurs (handlers et filters) JAX-*S.

Les développements se feront dans le projet services du TP précédent (implémentation de services en JAX-WS). Les handlers seront à utiliser avec l'implémentation bean “code généré” (i.e. la première version du service cours).

Ce TP pourra constituer un bonus pour le TP “implémentation de services” de sera rendu en même temps (un seul rendu pour les deux).

Handlers JAX-WS

Exemple

Créer une classe fr.univlyon1.tiw.tiw1.handlers.SimpleLogHandler contenant le code suivant:

SimpleLogHandler.java
package fr.univlyon1.tiw.tiw1.handlers;
 
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import javax.xml.ws.handler.LogicalHandler;
import javax.xml.ws.handler.LogicalMessageContext;
import javax.xml.ws.handler.MessageContext;
 
public class SimpleLogHandler implements LogicalHandler<LogicalMessageContext> {
 
    private final static Logger LOG = LoggerFactory.getLogger(SimpleLogHandler.class);
 
    @Override
    public void close(MessageContext ctx) {
    }
 
    @Override
    public boolean handleFault(LogicalMessageContext ctx) {
        LOG.warn("faute");
        return true;
    }
 
    @Override
    public boolean handleMessage(LogicalMessageContext ctx) {
        boolean outbound = (Boolean) ctx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
        LOG.info("message " + (outbound ? "sortant" : "entrant"));
        return true;
    }
 
}

Dans la classe de configuration Spring, ajouter un bean simpleLogHandler. Dans le code de mise en place du point d'accès au service de cours exposé à partir du Bean d'implémentation du service, créer une List<Handler> qui contiendra le bean simpleLogHandler, puis l'ajouter au point d'accès via setHandlers.

Déployer le service et tester l'affichage dans les logs en appelant le service avec SOAPUI.

Ajout d'information

Créer un nouveau handler qui récupère dans le header SOAP la valeur de l'élément user-email et l'injecte dans le contexte (propriété “personne.email”). Modifier le handler de log pour afficher cette propriété si elle est présente.

Ajouter ce handler dans la chaîne d'interception et modifier le test soapUI de votre service de commande pour y intégrer le nouveau header et tester.

Faire de même avec l'élément api-key et la propriété personne.key.

Récupération de l'objet client et authentification

Créer un handler logique d'authentification qui ajoute une propriété demandeur contenant un objet Personne correspondant à la propriété personne.email. Ce handler vérifie également que la clé (personne.key) est le miroir de l'email1). Si ce n'est pas le cas, le handler interdit l'accès au service.

Ajouter l'intercepteur dans la chaîne des services et tester.

Autorisation

Créer un handler logique qui interdit l'accès à l'opération facturer si le demandeur n'est pas un des intervenants du cours. Pour les autres opérations, l'accès sera autorisé.

Pseudo envoi d'un email d'inscription

Ajouter un champ de type javax.xml.ws.WebServiceContext dans la classe d'implémentation du service. Annoter ce champ avec @Resource afin que le contexte soit injecté via IoC. La méthode getMessageContext() permet alors de récupérer le contexte du message et les propriétés qui ont été ajoutées par les handlers. Modifier le code métier de l'opération inscription pour:

  1. récupérer l'objet Personne depuis le contexte
  2. envoyer un mail à cette personne et aux personnes inscrites dans le cours. L'envoi de mail sera simulé par une ligne dans le log.

<note tip>Seules les propriétés dont le scope est MessageContext.Scope.APPLICATION peuvent être accédées dans le bean qui code le service. Il faut donc penser à changer le scope de la propriété demandeur dans le handler d'authentification via

ctx.setScope("demandeur", Scope.APPLICATION);

</note>

Pour aller plus loin: JAX-RS

JAX-RS est le pendant de JAX-WS pour l'implémentation de services REST. CXF permet également de déployer des beans annotés via JAX-RS. Un système analogue aux handlers est disponible dans JAX-RS: les filters (c.f. API Filters de JAX-RS).

Exposer les personnes comme des ressources REST via JAX-RS et en limiter l'accès via un filter qui vérifiera que la présence d'une api-key dont la valeur est le miroir de l'email de la personne accédée.

1)
ceci n'est pas un TP de sécurité