Non esiste evento in Java EE. Ancora. Come parte di JSR375, la sicurezza gestita dal contenitore verrà completamente rielaborata poiché è attualmente scattered attraverso diverse implementazioni del contenitore e non è compatibile cross-contenitore. Questo è descritto in questa presentazione Java EE 8 Security API.
Esiste già un'implementazione di riferimento dell'API di sicurezza in corso, Soteria, sviluppata tra l'altro dal mio collega Arjan Tijms. Con la nuova API di sicurezza, CDI verrà utilizzato per attivare gli eventi di autenticazione che è possibile solo @Observes
. La discussione sulle specifiche è avvenuta nel this mailing list thread. Non è ancora concretamente implementato a Soteria.
Fino ad allora, supponendo l'autenticazione basata su FORM
in base alla quale il principal utente è memorizzato internamente nella sessione, la soluzione migliore è verificare manualmente un filtro servlet se c'è una presenza utente presente nella richiesta mentre la propria rappresentazione dell'utente loggato è assente nella sessione HTTP.
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
HttpServletRequest request = (HttpServletRequest) req;
String username = request.getRemoteUser();
if (username != null && request.getSession().getAttribute("user") == null) {
// First-time login. You can do your thing here.
User user = yourUserService.find(username);
request.getSession().setAttribute("user", user);
}
chain.doFilter(req, res);
}
Do atto che la registrazione di un filtro sulla /j_security_check
non è garantito per funzionare come contenitore decente gestirà internamente prima che i primi filtri sono colpiti, per ovvie ragioni di sicurezza (filtri forniti dagli utenti possono manipolare la richiesta in un cattivo modo, accidentalmente o volutamente).
Se invece capita di utilizzare un server Java EE utilizza il Undertow servletcontainer, come ad esempio WildFly, poi c'è un modo più pulito per agganciare i suoi eventi di notifica interna e quindi generare eventi CDI personalizzato.Questo è spiegato in this blog di Arjan Tijms. Come mostrato nel blog, in ultima analisi, è possibile finire con un fagiolo CDI come questo:
@SessionScoped
public class SessionAuthListener implements Serializable {
private static final long serialVersionUID = 1L;
public void onAuthenticated(@Observes AuthenticatedEvent event) {
String username = event.getUserPrincipal().getName();
// Do something with name, e.g. audit,
// load User instance into session, etc
}
public void onLoggedOut(@Observes LoggedOutEvent event) {
// take some action, e.g. audit, null out User, etc
}
}
Odio COSÌ per non dare la possibilità di invitare più di una volta! Detto questo, la soluzione Undertow renderà la tua webapp non completamente portatile, è qualcosa che sto cercando di evitare in questo momento.A questo punto, aggiungere un filtro per un intervallo di URL è probabilmente la soluzione che applicherò, ero solo un po 'preoccupato per il sovraccarico che potrebbe derivare da un filtro così ampiamente applicato, ma alla fine della giornata la maggior parte del tempo si tradurrà in una condizione non verificata se ... pensi che sarebbe un "overhead accettabile"? –
:) SO ha il concetto di [taglie] (http://meta.stackexchange.com/questions/16065/how-does-the-bounty-system-work). Inoltre, alcuni utenti hanno una lista dei desideri o un link di donazione sul loro profilo. Per quanto riguarda l'overhead, questo è davvero trascurabile. Forse qualche nanosecondo. Ci sono in una vera e propria applicazione web le cose migliori da ottimizzare. – BalusC