C'è un modo per ottenere la gestione delle sessioni o la sicurezza in modo programmatico in Jersey, ad es. gestione delle sessioni di applicazioni Web? Oppure le transazioni, le sessioni e la sicurezza sono tutte gestite dal contenitore in cui viene distribuita l'applicazione Jersey?jersey security and session management
risposta
La gestione delle sessioni è l'ambito del contenitore in cui viene distribuito Jersey. Nella maggior parte dei casi di produzione, verrà implementato all'interno di un contenitore che esegue la gestione delle sessioni.
Il codice seguente è un semplice esempio di una risorsa jersey che ottiene l'oggetto sessione e memorizza i valori nella sessione e li recupera nelle chiamate successive.
@Path("/helloworld")
public class HelloWorld {
@GET
@Produces("text/plain")
public String hello(@Context HttpServletRequest req) {
HttpSession session= req.getSession(true);
Object foo = session.getAttribute("foo");
if (foo!=null) {
System.out.println(foo.toString());
} else {
foo = "bar";
session.setAttribute("foo", "bar");
}
return foo.toString();
}
}
Grazie Jack, ne avevo bisogno perché dovevamo implementare una sorta di controllo degli accessi sui servizi web JAX-RS. Qualsiasi aiuto su questo sarà anche molto apprezzato .. Grazie in anticipo , Adhir – Adhir
@Jack Cox: Ho postato una domanda correlata qui: http://stackoverflow.com/questions/9676588/how-can-you-authenticate-using-the-jersey-client-against-a-jaas- enabled-web-serv Forse sapresti come farlo anche dal lato client (con jersey-client)? – carlspring
@Jack Cox, se ho un'applicazione con 1000 utenti loggati nello stesso momento e ogni set 'session.setAttribute (" username ", username)'. Java capisce che ci sono 1000 diverse sessioni ciascuna con una variabile chiamata 'username' con un valore diverso dalle altre? – kasavbere
La risposta di Jack alle sessioni è corretta. Sono specifici del contenitore in cui esegui, anche se le specifiche Servlet forniscono almeno la portabilità tra i contenitori JavaEE.
Per quanto riguarda la sicurezza, si ha almeno la possibilità di separarlo dal codice specifico JAX-RS utilizzando JaaS (servizio di autenticazione e autorizzazione Java) e uno servlet filter. Il filtro può essere utilizzato per imporre l'autenticazione HTTP e, in caso di autorizzazione riuscita, impostare il soggetto JaaS con i Principali appropriati. Le risorse JAX-RS possono controllare i Principali appropriati sull'argomento. Dal momento che controlli l'intero stack, dovresti essere in grado di fare affidamento su un utente autenticato nelle tue risorse (ma provalo!) E puoi imporre l'autorizzazione in base all'operazione corrente nel codice risorsa.
+1 Sembra una buona idea. Come hai potuto farlo funzionare su Grizzly? Ho aperto una nuova domanda. http://stackoverflow.com/questions/1682061/using-jaas-with-jersey-on-grizzly – User1
Per la sicurezza di Jersey dovresti dare un'occhiata al supporto OAuth della maglia. OAuth si adatta perfettamente quando si espongono le API per il proprio sistema a utenti esterni. Per esempio come la linkedin api
Si prega di correggere il collegamento – bekce
ho pensato che le sessioni è qualcosa che dovremmo mai l'uso in applicazioni RESTful ...
Yegor è giusto. Non dovremmo mai mantenere lo stato sul lato server a la applicazione web convenzionale. Se si desidera creare un'applicazione orientata SOA disaccoppiata, non è necessario utilizzare alcuna API/framework per i servizi Web REST. Se hai bisogno, o vuoi, di mantenere lo stato globale client-server sul lato del server stai costruendo implicitamente ciò che potremmo descrivere come un'app [web] orientata alla SOA, ma usando Jersey come un framework di sviluppo [web]. Inavvertitamente si distorce la natura di un servizio Web (REST o altro). È possibile farlo nel modo in cui è stato suggerito nella prima risposta, ma è necessario . Il risultato finale non è un servizio web, ma solo una normale app costruita con gli strumenti dei servizi web.
-_o
Questo non è sempre vero. Se la sessione viene utilizzata come metodo di memorizzazione nella cache delle risposte, si potrebbe sostenere che è utilizzata per migliorare le prestazioni. È ancora possibile scrivere un'applicazione senza stato, solo con una sessione come meccanismo di memorizzazione nella cache. I siti Web – Vladimir
come Facebook utilizzano sessioni in cima ai servizi Web per eseguire le applicazioni web. Non è intrinsecamente sbagliato. Potrebbe anche volere che un utente sia autenticato per utilizzare un servizio web, nel qual caso non si vorrebbe passare le credenziali ogni volta. – DiamondDrake
Ho risolto questo problema facendo i clienti aggiungere l'intestazione di autorizzazione e la sperimentazione nel Methode REST in questo modo:
@GET
@PRODUCES(MediaType.APPLICATION_JSON)
public String returnClients(@Context HTTPServletRequest request(
String auth = request.getHeader("Authorization");
Account acc = null;
if (auth!=null) {
Account acc = Utils.LoginAccount(auth);
}
if (acc == null)
// not logged in, handle it gracefully
In questo modo non v'è l'autenticazione senza avviare una sessione.
NB: Questo è totalmente insicuro a meno che non si stiano forzando le connessioni HTTPS, nel qual caso si potrebbe anche usare dropwizard-auth. – Lambart
Sì, è possibile.Jersey documentation dice:
informazioni di sicurezza di una richiesta è disponibile iniettando una JAX-RS esempio SecurityContext utilizzando annotazioni @Context. L'istanza del contesto di sicurezza iniettata fornisce l'equivalente della funzionalità disponibile sull'API HttpServletRequest. Il contesto di sicurezza iniettato dipende dall'effettiva distribuzione dell'applicazione Jersey. Ad esempio, per un'applicazione Jersey distribuita in un contenitore Servlet, il Jersey SecurityContext incapsulerà le informazioni da un contesto di sicurezza recuperato dalla richiesta servlet. In caso di un'applicazione Jersey distribuita su un server Grizzly, SecurityContext restituirà le informazioni recuperate dalla richiesta Grizzly.
Esempio:
@Path("basket")
public ShoppingBasketResource get(@Context SecurityContext sc) {
if (sc.isUserInRole("PreferredCustomer") {
return new PreferredCustomerShoppingBasketResource();
} else {
return new ShoppingBasketResource();
}
}
o
@Path("resource")
@Singleton
public static class MyResource {
// Jersey will inject proxy of Security Context
@Context
SecurityContext securityContext;
@GET
public String getUserPrincipal() {
return securityContext.getUserPrincipal().getName();
}
}
O se volete la sicurezza fuori dalla scatola con annotazioni controllare these docs.
Jersey permette inoltre di personalizzare il SecurityContext: metodo di
Il SecurityContext possono essere recuperate direttamente dal ContainerRequestContext via getSecurityContext(). È anche possibile sostituire il SecurityContext predefinito in un contesto di richiesta con uno personalizzato utilizzando il metodo setSecurityContext (SecurityContext). Se si imposta un'istanza SecurityContext personalizzata in ContainerRequestFilter, questa istanza del contesto di sicurezza verrà utilizzata per l'iniezione nei campi della classe di risorsa JAX-RS . In questo modo è possibile implementare un filtro di autenticazione personalizzato che può impostare il proprio SecurityContext per essere utilizzato. Per garantire l'esecuzione anticipata del filtro di richiesta dell'autenticazione personalizzata , imposta la priorità del filtro su AUTHENTICATION utilizzando le costanti dalle priorità. Un'esecuzione anticipata dell'autenticazione del filtro assicurerà che tutti gli altri filtri, risorse, metodi risorsa e localizzatori di risorse secondarie vengano eseguiti con l'istanza di SecurityContext personalizzata .
Vedere examples on how to use request filters with Jersey. E controlla il mio esempio seguente:
import javax.annotation.Priority;
import javax.ws.rs.Priorities;
@Provider
@Priority(Priorities.AUTHENTICATION)
public class AuthRequestFilter implements ContainerRequestFilter {
@Context
HttpServletRequest webRequest;
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
final HttpSession session = webRequest.getSession();
requestContext.setSecurityContext(new SecurityContext() {
@Override
public Principal getUserPrincipal() {
return new PrincipalImpl((String)session.getAttribute("USER_NAME"));
}
@Override
public boolean isUserInRole(String s) {
return false;
}
@Override
public boolean isSecure() {
return false;
}
@Override
public String getAuthenticationScheme() {
return null;
}
});
}
}
Avviso! This was introduced in Jersey 2.4. Glassfish 4.0.0 utilizza la vecchia maglia 2.0, pertanto è necessario upgrade Jersey using these tips (non è dimostrato che funzioni bene). O il modo migliore è scaricare the nightly build of Glassfish 4.0.1. ma al momento non è completamente stabile. Spero che la nuova versione sarà rilasciata presto.
UPDATE: Al momento (2014/02/14) Glassfish 4.0.1 nightly build utilizza Jersey 2.5.1 e iniezione contesto funziona alla grande.
Ottima risposta! Grazie –
È possibile utilizzare @path per raggruppare i servizi nello spazio per nome singolo. esempio.
@Path("/helloworld")
public class HelloWorld {
@GET
@Produces("text/plain")
public String hello() {
return "";
}
}
Instead of @Path("/helloworld") use
@Path("admin/helloworld") to expose you class as rest and bind filter on "admin/"
in web.xml as below.
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>/</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>myfilter</filter-name>
<filter-class>com.Filterclass</filter-class>
</filter>
<filter-mapping>
<filter-name>myfilter</filter-name>
<url-pattern>/rest/admin/*</url-pattern>
</filter-mapping>
public class Filterclass implements Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
try{
chain.doFilter(request, response);
}catch(Exception e){
e.printStackTrace();
}
}
}
è possibile convalidare voi sessione in questa classe filtro.
Ho appena iniziato a indagare anche su questo. Ti risponderò se trovassi qualcosa –