web-dev-qa-db-fra.com

Quel est le bon remplacement du Resteasy 3.X PreProcessInterceptor?

Je crée un service de repos en utilisant un mécanisme d'authentification/autorisation comme décrit dans ce tutoriel: http://howtodoinjava.com/2013/06/26/jax-rs-resteasy-basic-authentication-and-authorization- tutoriel /

Fondamentalement, il utilise l'interface PreProcessInterceptor pour analyser la méthode cible pour les annotations (à partir du package javax.annotation.security ) qui décrivent les rôles requis pour accéder à cette méthode. Comme l'authentificateur ici est un intercepteur, il peut annuler l'invocation de la méthode cible, renvoyant un 401 (non autorisé) si nécessaire.

Le problème ici est que l'interface org.jboss.resteasy.spi.interception.PreProcessInterceptor est déconseillée dans la version actuelle de RestEasy (3.0.1), et j'ai des problèmes à essayer d'implémenter le même comportement avec les interfaces JAX-RS standard .

J'utilise l'interface javax.ws.rs.ext.ReaderInterceptor pour intercepter l'appel. Mais le serveur ne l'appelle jamais: l'intercepteur est simplement ignoré.

J'enregistre les intercepteurs/ressources de la même manière que je l'ai fait avec l'ancien PreProcessInterceptor, et j'utilise les mêmes annotations @Provider et @ServerInterceptor:

ServerApplication:

public class ServerApplication extends javax.ws.rs.core.Application {

     private final HashSet<Object> singletons = new LinkedHashSet<Object>();

     public ServerApplication() {
         singletons.add(new SecurityInterceptor());
         singletons.add( ... ); //add each of my rest resources
     }

    @Override
    public Set<Class<?>> getClasses() {
        HashSet<Class<?>> set = new HashSet<Class<?>>();
        return set;
    }

    @Override
    public Set<Object> getSingletons() {
        return singletons;
    }
}

SecurityInterceptor:

@Provider
@ServerInterceptor
public class SecurityInterceptor implements javax.ws.rs.ext.ReaderInterceptor {
     @Override
     public Object aroundReadFrom(ReaderInterceptorContext context){
            //code that is never called... so lonely here...
     }
}

Avez-vous des idées sur la façon de résoudre ce problème?

Je vous remercie.

29
Gilberto Torrezan

RESTEasy 3.x.x est conforme à la spécification JAX-RS 2.0.

Ce que vous essayez de faire pourrait être accompli (peut-être mieux) avec:

@Provider
public class SecurityInterceptor 
      implements javax.ws.rs.container.ContainerRequestFilter {
     @Override
     public void filter(ContainerRequestContext requestContext){
       if (not_authenticated){ requestContext.abortWith(response)};
     }
}

puisque le ReaderInterceptor n'est invoqué que si le MessageBodyReader.readFrom sous-jacent est appelé par le pipeline JAX-RS standard, pas à partir du code d'application.

Cependant, la raison pour laquelle votre intercepteur n'est pas appelé pourrait être l'annotation @ServerInterceptor, Qui est une extension RESTEasy.

La spécification indique au §6.5.2 qu'un intercepteur est enregistré globalement, sauf si @Provider Est annoté avec une annotation @NameBinding, Mais je ne sais pas si RESTEasy peut gérer un @ServerInterceptor s'il n'est pas explicitement enregistré comme indiqué dans l'intercepteur RestEASY n'est pas appelé

26
Carlo Pellegrini

Si vous avez besoin d'accéder au sous-jacent Java.lang.reflect.Method (comme vous pouviez obtenir en implémentant AcceptedByMethod), vous pouvez effectuer les opérations suivantes:

ResourceMethodInvoker methodInvoker = (ResourceMethodInvoker) 
            requestContext.getProperty("org.jboss.resteasy.core.ResourceMethodInvoker");
Method method = methodInvoker.getMethod();
4
mtpettyp

Je voulais également avoir accès au sous-jacent Java.lang.reflect.Method et essayé la réponse de mtpettyp avec Resteasy 3.0.8, mais qui renvoyait null lors de l'appel à getProperty. J'utilise également Spring et Resteasy-Spring, même si je ne pense pas que cela devrait avoir un impact sur cela.

Si vous rencontrez ma situation et que vous implémentez une post-correspondance ContainerRequestFilter (vous devez en quelque sorte le faire si vous vous attendez à obtenir la méthode de ressource correspondante de toute façon), vous pouvez réellement convertir le ContainerRequestContext en implémentation Resteasy a pour le scénario Post Match. PostMatchContainerRequestContext a une référence à ResourceMethodInvoker.

public void filter(ContainerRequestContext context) throws IOException {
    PostMatchContainerRequestContext pmContext = (PostMatchContainerRequestContext) context;

    Method method = pmContext.getResourceMethod().getMethod();

    /* rest of code here */
}
3
Rich