JSF bei Session-Timeout Weiterleitung auf spezielle Login-Seite

Q

quazogen

Gast
Hallo,

ich habe ein Problem mit dem Umgang beim Timeout bei JSF 2.0. Und zwar habe ich in der web.xml einen Session Listener und einen SessionTimeoutFilter definiert. Nun möchte ich in dem SessionListener bei dem sessionDestroyed-Event eine Weiterleitung auf die Login-Seite implementieren. Da die Login-Seite sich für verschieden Nutzer unterscheidet hole ich mir hier aus der Session die nötigen Informationen. Das klappt auch soweit. Das Problem ist, dass ich hier kein FacesContext-Objekt habe und mir somit nicht die Navigation zur Verfügung steht. (Ich bräuchte die URLs und die redirect-Funktion). Gibt es eine Möglichkeit ein FacesContext-Objekt zu erzeugen oder zu holen? Bin für jeden Tipp dankbar.

e.: Ich habe eine Logout-Methode, die ich gerne für die Weiterleitung nutzen möchte, jedoch bekomme ich hier immer eine NullPointerException, weil das FacesContext-Objekt null ist.

web.xml
[XML]<listener-class>
myPackage.MySessionListener
</listener-class>
</listener>
<filter>
<filter-name>SessionTimeoutFilter</filter-name>
<filter-class>
myPackage.SessionTimeoutFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>SessionTimeoutFilter</filter-name>
<url-pattern>*.jsf</url-pattern>
</filter-mapping>
<session-config>
<session-timeout>1</session-timeout>
</session-config>[/XML]

mySessionListener
Code:
public void sessionDestroyed(HttpSessionEvent event) {
		HttpSession session = event.getSession();
		LoginBean loginBean = (LoginBean) session.getAttribute("loginBean");
 
Zuletzt bearbeitet von einem Moderator:
Q

quazogen

Gast
Erstmal vielen Dank,

ich weiß aber nicht ob dieser Thread so perfekt auf mein Problem passt. Es geht mir ja nicht um ein Rechtesystem. Das läuft alles soweit. Mein Problem besteht in dem Ablauf der Session.

Ich gebe einfach mal ein Beispiel:

eine Seite für Fußballfans und jeder Verein hat eine eigene Login-Seite:
Code:
http://www.fussballfans.de?login.jsf&region=nrw&team=fcn

Die Informationen über einen User stehen in einer Bean. (Lieblingsverein, Region etc.) Die Bean ist als Attribut in der Session gespeichert. Läuft die Session nun ab gehen diese Informationen ja verloren. Eigentlich möchte ich nun, dass der Benutzer bei einem Klick nach dem Ablauf wieder auf die passende Login-Seite geleitet wird. Ich wäre aber auch zufrieden damit, wenn er direkt nach Ablauf der Session (also ohne weiteren Klick) auf diese Seite gelangt. Dafür auch der Ansatz mit dem Session Listener, jedoch steht mir hier das FacesContext-Objekt nicht zur Verfügung.
Ich komme da gerade nicht weiter, mit dem Ansatz von Ed Burns Dealing Gracefully with ViewExpiredException in JSF2 | Java.net komme ich auch nicht weiter.
 
Zuletzt bearbeitet von einem Moderator:

JimPanse

Bekanntes Mitglied
???:L Ich sehe da keine Rollen-Rechte??? Ich kopier es dir einfach nochmal zusammen:

Java:
public class SecurityPhaseListener implements PhaseListener, Serializable {
    @Override
    public void afterPhase(PhaseEvent arg0) {
            final FacesContext facescontext = arg0.getFacesContext();
        
        // not exist yet (non-faces-request) 
        if (facescontext.getViewRoot() == null) {
            facescontext.getApplication().getNavigationHandler().handleNavigation(facescontext, null, "index");
            // ignore other phases
            facescontext.renderResponse();
        } else {
 
            // current view identifier
            final String viewId = facescontext.getViewRoot().getViewId();
 
            final boolean loginPage = viewId.lastIndexOf("index") > -1;
//  JAAS
  //          final boolean login = facescontext.getExternalContext().getRemoteUser() != null;
// 
final boolean login  = (facescontext.getExternalContext().getSessionMap().get("security-token") != null);
            
            // not login page and user is not login - redirect to login page
            if (!loginPage && !login) {
 
                facescontext.getApplication().getNavigationHandler().handleNavigation(facescontext, null, "index");
                // ignore other phases
                facescontext.renderResponse();
 
                // login page and user is login - redirect to start page
            } else if (loginPage && login) {
                facescontext.getApplication().getNavigationHandler().handleNavigation(facescontext, null, "start");
                // ignore other phases
                facescontext.renderResponse();
            }
        }

    }
 

    @Override
    public void beforePhase(PhaseEvent arg0) {
    }
 
    @Override
    public PhaseId getPhaseId() {
        return PhaseId.RESTORE_VIEW;
    }
 
}


[XML]<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="2.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
Java EE : XML Schemas for Java EE Deployment Descriptors
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">
<lifecycle>
<phase-listener>de.my.package.SecurityPhaseListener</phase-listener>
</lifecycle>
<navigation-rule>
<from-view-id>/*</from-view-id>
<navigation-case>
<from-outcome>index</from-outcome>
<to-view-id>/index.xhtml</to-view-id>
<redirect />
</navigation-case>
<navigation-case>
<from-outcome>start</from-outcome>
<to-view-id>/public/start.xhtml</to-view-id>
<redirect />
</navigation-case>
</navigation-rule>
</faces-config>[/XML]


1. Benutzer meldet sich an: security-token in der Session ablegen (bsp. die Userid).
2. Anwendung in öffentlich und geschlossen Bereich einteilen
3. Session läuft aus d.h. token nicht mehr vorhanden -> user zur login seite

oder
shiro

oder

Wenn du bei der Listener Variante bleiben möchtest:

access-facescontext-from-servlet
 
Q

quazogen

Gast
Ich habe jetzt mal die Variante mit dem SecurityPhaseListener verfolgt.

Wie finde ich da jetzt heraus, dass meine Session abgelaufen ist?
 

mario87b

Aktives Mitglied
Hast du es hinbekommen?

Da hab ich mal ne Frage zu. Ich kann ja meine Session ID irgendwo speichern - in einem Cookie zum Beispiel.

Wenn der Nutzer dann irgendwann aufwacht und mal wieder an den Rechner geht, check ich das Cookie nach der Session ID und check ob die Session noch aktiv ist, wenn nicht dann ab zum Login.

Geht das?
 

JimPanse

Bekanntes Mitglied
Da hab ich mal ne Frage zu. Ich kann ja meine Session ID irgendwo speichern - in einem Cookie zum Beispiel.

Wenn der Nutzer dann irgendwann aufwacht und mal wieder an den Rechner geht, check ich das Cookie nach der Session ID und check ob die Session noch aktiv ist, wenn nicht dann ab zum Login.

Geht das?


Macht keinen Sinn weil eine Session in der Regel nur eine bestimmte Lebensdauer besitzt und wenn diese abgelaufen bzw die Session nicht mehr vorhanden ist - kannst du den Benutzer auch ohne vorher einen Cookie zu checken zum Anmeldeformular weiterleiten.
 

mario87b

Aktives Mitglied
Ja, ok, versteh ich.
Es wäre für mich der erste Versuch, grundsätzlich kann ich via Cookie schon eine noch bestehende Session weiter nutzen, oder?
 
Q

quazogen

Gast
Also ich hatte die letzten Wochen glücklicherweise andere Aufgaben, hänge aber immer noch bei diesem Problem. Mir würde aber aktuell eine kleinere Lösung reichen:
Session läuft ab -> Benutzer klickt einen Link an -> Benutzer wird zu einer Timeout-Seite geleitet

Aber auch diese Variante klappt einfach nicht.
Ich habe einen SessionTimeoutFilter definiert. Die Klasse sieht wie folgt aus:

Java:
public class SessionTimeoutFilter implements Filter {

 private String timeoutPage = "sessionExpired.jsf";

 public void init(FilterConfig filterConfig) throws ServletException {
 }

 public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException,
   ServletException {

  if ((request instanceof HttpServletRequest) && (response instanceof HttpServletResponse)) {
   HttpServletRequest httpServletRequest = (HttpServletRequest) request;
   HttpServletResponse httpServletResponse = (HttpServletResponse) response;
   
   // is session expire control required for this request?
   if (isSessionControlRequiredForThisResource(httpServletRequest)) {
    
    // is session invalid?
    if (isSessionInvalid(httpServletRequest)) {
     String timeoutUrl = httpServletRequest.getContextPath() + "/" + getTimeoutPage();
     
     httpServletResponse.sendRedirect(timeoutUrl);
     return;
    }
   }
  }
  filterChain.doFilter(request, response);
 }

 /**
  * 
  * session shouldn't be checked for some pages. For example: for timeout page..
  * Since we're redirecting to timeout page from this filter,
  * if we don't disable session control for it, filter will again redirect to it
  * and this will be result with an infinite loop... 
  */
 private boolean isSessionControlRequiredForThisResource(HttpServletRequest httpServletRequest) {
  String requestPath = httpServletRequest.getRequestURI();
  
  boolean controlRequired = !StringUtils.contains(requestPath, getTimeoutPage());
  
  return controlRequired;
 }

 private boolean isSessionInvalid(HttpServletRequest httpServletRequest) {
  boolean sessionInValid = (httpServletRequest.getRequestedSessionId() != null)
    && !httpServletRequest.isRequestedSessionIdValid();
  return sessionInValid;
 }

 public void destroy() {
 }

 public String getTimeoutPage() {
  return timeoutPage;
 }

 public void setTimeoutPage(String timeoutPage) {
  this.timeoutPage = timeoutPage;
 }
 
}

Ich habe mir das Ganze auch mal in Firebug angeschaut.
Beim Klick wird ein Anfrage-Header für die angeforderte Seite gesendet, als Response erhalte ich dann:
- 302 Moved Temporarily
- Location: http://localhost:8080/project/sessionExpired.jsf

Danach fragt der Browser direkt die sessionExpired.jsf an:
- GET /project/sessionExpired.jsf HTTP/1.1

und bekommt als Antwort ein OK:
- HTTP/1.1 200 OK

Die Seite bleibt aber gleich. Wo liegt da der Fehler?
 

F.S.WhiTeY

Bekanntes Mitglied
Java:
public class SessionTimeoutFilter implements Filter {
 

 FilterConfig conf;
 private String timeoutPage = "sessionExpired.jsf";
 
 public void init(FilterConfig filterConfig) throws ServletException {
              //Gleich angewöhnen macht es später einfacher ;)
              conf = filterConfig;
 }
 
 public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
 
   
   HttpServletRequest requ = (HttpServletRequest) request;
   HttpServletResponse respon = (HttpServletResponse) response;
   
        // is session expire control required for this request?
        if (isSessionControlRequiredForThisResource(requ)) {
    
              if (isSessionInvalid(requ)) {
                     String timeoutUrl = requ.getContextPath() + "/" + this.timeoutPage;
     
                     respon.sendRedirect(timeoutUrl);
                     //Wobei respon.sendRedirect("sessionExpired.jsf"); reichen sollte... eigentlich
 
               }else{
                    filterChain.doFilter(requ, respon);
               }
        }
 }

Vilt. sollte ich noch erklären, dass wenn die
Code:
filterChain.doFilter(requ, respon);
nicht aufgerufen wird, auch nicht das nächste element im chain aufgerufen wird. Das ist genau das wass du willst, der chain soll abbrechen und nur der Redirect aufgerufen werden.

Ein Fehler war also zu 99.99% das
Code:
filterChain.doFilter(requ, respon);
am Ende.

LG
 
Zuletzt bearbeitet:

F.S.WhiTeY

Bekanntes Mitglied
Noch eine Anmerkung: Sprechende Variablen- und Methodennamen rocken zwar, aber mann muss es nicht übertreiben.

isSessionControlRequiredForThisResource() == isControlRequired()
isSessionInvalid() == isInvalid
 
Q

quazogen

Gast
Erstmal danke für die Hilfe, aber das Problem besteht nach wie vor. Die Seite bleibt beim Laden hängen und ich werde nicht auf die Timeout-Page weitergeleitet.

Das
Java:
filterChain.doFilter(requ, respon);
am Ende wurde doch schon durch das
Java:
return;
abgefangen.

Woran könnte das sonst liegen?
 

JimPanse

Bekanntes Mitglied
Erstmal danke für die Hilfe, aber das Problem besteht nach wie vor. Die Seite bleibt beim Laden hängen und ich werde nicht auf die Timeout-Page weitergeleitet.

Das
Java:
filterChain.doFilter(requ, respon);
am Ende wurde doch schon durch das
Java:
return;
abgefangen.

Woran könnte das sonst liegen?


Wenn du schon kopierst - Warum kopierst du dann nicht gleich richtig?????

Ich habe die Lösung von 'jules poit' getestet und sie funktioniert einwandfrei:
SessionTimeoutFilter


Greetz
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
J Crash bei session timeout Web Tier 3
T Problem bei Session-Timeout Web Tier 3
I Gleiche Session von EJB Container in JSF Container verwenden? Web Tier 21
R Session löschen Web Tier 3
J Session ist nach Klick auf Zurück-Button wieder aktiv Web Tier 3
jann Servlet Bei jedem Request wird eine neue Session erstellt. Web Tier 6
J Session Servlet - JavaScript Web Tier 6
M Session closed - und nun? Web Tier 1
F JSF synchronized(session) Frage ? Web Tier 1
F JSF p:selectOneMenu Session Web Tier 10
T JSF Problem wenn Session abgelaufen ist Web Tier 6
D JSF Überprüfen der Session ID in JSF und JAVA Web Tier 9
R Servlet Resource laden für SMTP - Session Web Tier 4
B JSF Mojarra 2.1.5: java.lang.IllegalStateException: Cannot create a session after the response has been Web Tier 7
R JSF Session Handling Web Tier 3
X JSP Auslesen der Daten einer Session Web Tier 3
X Managed Bean Scope zwischen Request und Session gesucht Web Tier 6
crashfinger JSP Session verloren bei DNS Servernamen & IE Web Tier 6
C session trackung auf einfacher web-site Web Tier 17
F JSF Session-Kolision Web Tier 3
R Zugriff auf Session direkt auf JSF-Seite Web Tier 2
H JSF Session Initialisierung Web Tier 2
E JSP Browser Tab Session Web Tier 7
F Session Tutorial Web Tier 5
T JSP Session Login - Sicherheit Web Tier 4
J Loginbereich mit Session und Datenbank Web Tier 5
M 2 Cookies in der session (cocoon 2.2) Web Tier 4
F Richtiges Session Management mit Servlets Web Tier 4
P JSP: Liste in Bean über Session aufbauen Web Tier 6
7 Struts+AJAX- Session-Handling? Web Tier 2
B JSF session bean mit worker thread updaten Web Tier 7
M session Speicherort - ID ändern Web Tier 8
V ANFÄNGER : eigene Session Web Tier 3
V DatenbankConnection an Session hängen Web Tier 4
P session.removeAttribute Web Tier 3
K Orientierungslosigkeit: Webservice+Ajax(echo2)+Session-Management Web Tier 4
O struts - Gültigkeit einer Action an Session binden?! Web Tier 4
D JSF: Best Practice "Session invalidate nach Schließen des Browsers"? Web Tier 3
T Unbegrenzte Session Web Tier 14
D tapestry 5 session Web Tier 2
J Struts 2 session ID auslesen? Web Tier 5
M [J2EE] Session-Save Static-Objects? Web Tier 6
S Problem mit Session - Übergabe von Kontext zu Kontext Web Tier 2
F JSF: Beans in Session oder Request? Web Tier 4
H JSF - Bean (scope session) - Verfallsdatum? Web Tier 3
M JSF refresh vs. session scope Web Tier 9
G Session in Servlet Starten und mit JSTL auslesen Web Tier 2
G Servlet - Von Parametern umstellen auf Session Web Tier 8
G jsf session erstellen Web Tier 10
rambozola session attribut in servlets und jsps Web Tier 11
M JSF session.invalidate() klappt nicht Web Tier 3
G Session.invalide() funktioniert nicht richtig Web Tier 2
O Connection Pool: "Timeout waiting for idle object" Exception Web Tier 3
D Servlet Servlet Weiterleitung static html Web Tier 5
T JSF Primefaces: DataTable Ajax Update - Weiterleitung von anderer Seite Web Tier 11
D Sessiontimeout Exception bei Weiterleitung Web Tier 10
F JSP Weiterleitung Web Tier 7
S Weiterleitung, wenn angemeldet Web Tier 8
A JSF Weiterleitung funktioniert einfach nicht Web Tier 2
I Automatische Weiterleitung JSF mit Aufruf einer Methode Web Tier 2
Tandibur JSF: Verlinkung mittels Button, bedingte Weiterleitung Web Tier 4
J [JSP] Abfrage der URL und automatische Weiterleitung Web Tier 6
D JSF+Weiterleitung zu einer Login-Page Web Tier 1
M Bei Weiterleitung von Servlet zu JSP: URL der JSP anzeigen Web Tier 6

Ähnliche Java Themen

Neue Themen


Oben