2013-07-11 10 views
27

Sto costruendo servizio riposo utilizzando un meccanismo di autenticazione/autorizzazione come descritto in questo tutorial: http://howtodoinjava.com/2013/06/26/jax-rs-resteasy-basic-authentication-and-authorization-tutorial/Qual è la corretta sostituzione di Pre-Process 3.X PreProcessInterceptor?

Fondamentalmente si utilizza l'interfaccia PreProcessInterceptor per analizzare il metodo di destinazione per le annotazioni (da javax.annotation.security pacchetto) che descrivono i ruoli richiesti per accedere quel metodo. Poiché l'autenticatore qui è un intercettore, può annullare l'invocazione del metodo di destinazione, restituendo un 401 (non autorizzato) se necessario.

Il problema qui è che l'interfaccia org.jboss.resteasy.spi.interception.PreProcessInterceptor è deprecata nella versione RestEasy corrente (3.0.1) e sto riscontrando problemi nel tentativo di implementare lo stesso comportamento con lo standard Interfacce JAX-RS.

Sto utilizzando l'interfaccia javax.ws.rs.ext.ReaderInterceptor per intercettare la chiamata. Ma in qualche modo il server non lo chiama mai: l'intercettore viene semplicemente ignorato.

sto registrando le intercettori/risorse allo stesso modo come ho fatto con l'ex PreProcessInterceptor, e utilizzando lo stesso @Provider e le annotazioni @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... 
    } 
} 

Eventuali approfondimenti su come posso risolvere questo problema?

Grazie.

+2

Aggiornamento dell'esempio completo in un altro post: http://howtodoinjava.com/2013/07/25/jax-rs-2-0-resteasy-3-0-2-final-security-tutorial/ – lokesh

risposta

25

RESTEasy 3.x.x è conforme alle specifiche JAX-RS 2.0.

Che cosa si sta cercando di fare potrebbe essere realizzato (forse meglio) con:

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

dal momento che il ReaderInterceptor viene richiamato solo se il sottostante MessageBodyReader.readFrom è chiamato dal JAX-RS gasdotto standard, non fromthe codice dell'applicazione .

Il motivo per cui l'interceptor non viene chiamato, tuttavia, potrebbe essere l'annotazione @ServerInterceptor, che è un'estensione RESTEasy.

Gli stati spec in §6.5.2 che un intercettore è registrato a livello globale, a meno che il @Provider è annotato con un @NameBinding annotazione, ma non so se RESTEasy in grado di gestire un @ServerInterceptor se non è esplicitamente registrato come illustrato nella RestEASY Interceptor Not Being Called

+0

Utilizzo di ContainerRequestFilter, come posso ottenere le annotazioni del metodo di destinazione? Il filtro/intercettore deve sapere che per consentire o negare correttamente l'invocazione, in base ai ruoli dell'utente. –

+0

'ContainerRequestFilter.getUriInfo(). GetMatchedResources()' restituisce l'elenco degli oggetti risorsa corrispondenti. Qui puoi analizzare le annotazioni corrispondenti ai metodi effettivi chiamati –

+1

Penso che tu intendessi "requestContext.getUriInfo(). GetMatchedResources()'. Ad ogni modo, questo metodo non è altrettanto facile da usare come nel precedente 'PreProcessInterceptor', dal momento che non ho accesso diretto al target' java.lang.reflect.Method'. Ma segnerò la risposta come accettata, poiché risolve il problema. –

4

Se avete bisogno di ottenere l'accesso al sottostante java.lang.reflect.Method (come hai utilizzato per essere in grado di ottenere mediante l'attuazione di AcceptedByMethod), è possibile effettuare le seguenti operazioni:

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

Come ottenere un httpRequest da requestContext. Ho il requisito di leggere InputStream da httpRequest. come fare? O è un modo in cui posso ottenere InputStream dal containerrequestcontext? – arunsankarkk

+0

Ricevo il riferimento null da methodInvoker, non so perché. –

2

volevo anche ottenere l'accesso alla u nderlying java.lang.reflect.Method e ha provato la risposta di mtpettyp con Resteasy 3.0.8, ma restituiva null sulla chiamata getProperty. Sto anche usando Spring e resteasy-spring anche se non credo che questo dovrebbe avere un impatto su tutto questo.

Se si verifica la mia situazione e si sta implementando un Corrispondenza postale ContainerRequestFilter (in qualche modo è necessario se si prevede di ottenere comunque il metodo di risorsa corrispondente), è possibile trasmettere lo ContainerRequestContext all'implementazione Resteasy ha per Post Scenario di corrispondenza. Lo PostMatchContainerRequestContext ha un riferimento a ResourceMethodInvoker.

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

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

    /* rest of code here */ 
}