Ich habe mir viele Beiträge zu diesem Thema angesehen, konnte aber keine Lösung finden, die in meinem Fall funktioniert.
Ich verwende Java EE 6 mit JSF 2.0 (auf JBoss AS 7.1 implementiert)
In meinem web.xml
habe ich:
<session-config>
<session-timeout>1</session-timeout>
</session-config>
und I Der Benutzer soll auf die Anmeldeseite umgeleitet werden, wenn die Sitzung automatisch abgelaufen ist.
was ich versucht habe:
Ansatz 1: Verwenden des Filters
Ich habe den folgenden Filter ausprobiert:
@WebFilter()
public class TimeOutFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
System.out.println("filter called");
final HttpServletRequest req = (HttpServletRequest) request;
final HttpSession session = req.getSession(false);
if (session != null && !session.isNew()) {
chain.doFilter(request, response);
} else {
System.out.println("Has timed out");
req.getRequestDispatcher("/logon.xthml").forward(request, response);
}
}
@Override
public void destroy() {
}
}
Im web.xml
habe ich versucht
<filter-mapping>
<filter-name>TimeOutFilter</filter-name>
<url-pattern>*.xhtml</url-pattern>
</filter-mapping>
und
<filter-mapping>
<filter-name>TimeOutFilter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
Der Filter arbeitet so, wie er bei jeder Anforderung aufgerufen wird (Protokollierung von "Fiter" in der Konsole). Es wird jedoch nicht aufgerufen, wenn die Sitzung abläuft.
Ansatz 2: HttpSessionLister
Ich habe versucht, eine HttpSessionListerner
zu verwenden. Die aufgerufene Methode hat folgende Signatur:
public void sessionDestroyed(HttpSessionEvent se) {
}
Ich konnte nicht auf eine bestimmte Seite umleiten. Wenn ich einen Benutzer umleiten möchte, verwende ich normalerweise die NavigationHandler
der FacesContext
, aber in diesem Fall gibt es keine FacesContext
(FacesContext.getCurrentInstance()
gibt null
zurück).
Gemäß diesem post kann der HttpListener den Benutzer nicht umleiten, da er nicht Teil einer Anforderung ist.
Frage
Was ist der beste Weg, um dieses Problem zu lösen? Was kann ich tun, um einen der beiden oben genannten Ansätze in die Tat umzusetzen?
Sie können keine HTTP-Antwort senden, solange der Client keine HTTP-Anforderung sendet. So einfach ist das. Genau so funktioniert HTTP. Das Internet hätte ansonsten ganz anders ausgesehen, wenn eine Website in der Lage war, eine HTTP-Antwort ohne Nachfragen per Push zu senden, ohne dass der Client dies verlangt hatte.
Ein JavaScript-basierter Heartbeat basierend auf der Tastatur-/Mausaktivität des Kunden wie beantwortet hier oder ein Meta refresh
-Header wie beantwortet hier wäre die Lösung, wenn Sie im Grunde eine einseitige Webanwendung haben (also Sie verwenden praktisch nicht den Sitzungsbereich, sondern den Ansichtsbereich. Dies funktioniert jedoch nicht gut, wenn Sie die Seite in mehreren Registerkarten/Fenstern in derselben Sitzung öffnen.
Websockets ist theoretisch die richtige Lösung, um etwas an den Client zu senden. Dies erfordert jedoch eine aktive Sitzung. Hühnerei-Problem. Es funktioniert auch nicht in älteren Browsern, die derzeit noch relativ häufig verwendet werden, und sollte daher nur zur schrittweisen Verbesserung verwendet werden.
Am besten definieren Sie einfach eine Fehlerseite, die den Fall behandelt, wenn der Endbenutzer eine Aktion ausführt, während die Sitzung abgelaufen ist. Siehe auch javax.faces.application.ViewExpiredException: View konnte nicht wiederhergestellt werden .
In HttpSessionListerner können Sie keine Antwort an den Benutzer senden. Eine gute Möglichkeit, dies zu erreichen, ist das Abfragen. Der Browser sendet in regelmäßigen Abständen HTTP-Anforderungen und erhält sofort eine Antwort.
Dafür gibt es viele Möglichkeiten:
Sie können normales Javascript zum Abfragen verwenden: Dies funktioniert in einer Browserübergreifenden Umgebung.
funktion Refresh () {
// make Ajax call here, inside the callback call:
setTimeout(refresh, 5000);
// ...
}
// initial call, or just call refresh directly
setTimeout (Refresh, 5000);
Sie können Web Sockets verwenden. Web-Socket-Spezifikation ist unter dem folgenden Link vorhanden: