wake-up-neo.net

Umleitung nach dem Timeout von HttpSession

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?

10
phoenix7360

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 .

15
BalusC

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:

  1. 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);

  2. Sie können Web Sockets verwenden. Web-Socket-Spezifikation ist unter dem folgenden Link vorhanden:

    http://dev.w3.org/html5/websockets/

0
Ankit Zalani