J'ai consulté de nombreux articles sur ce sujet, mais je n'ai pas pu trouver de solution qui fonctionne dans mon cas.
J'utilise Java EE 6 avec JSF 2.0 (déployé sur JBoss AS 7.1)
Dans mon web.xml
j'ai:
<session-config>
<session-timeout>1</session-timeout>
</session-config>
et I souhaite que l'utilisateur soit redirigé vers la page de connexion lorsque la session expire automatiquement.
ce que j'ai essayé:
Approche 1: utiliser un filtre
J'ai essayé le filtre suivant:
@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() {
}
}
Dans le web.xml
j'ai essayé
<filter-mapping>
<filter-name>TimeOutFilter</filter-name>
<url-pattern>*.xhtml</url-pattern>
</filter-mapping>
et
<filter-mapping>
<filter-name>TimeOutFilter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
Le filtre fonctionne comme il est appelé à chaque requête (enregistrement du "fiter appelé" dans la console). Cependant, il n'est pas appelé lorsque la session arrive à expiration.
Approche 2: HttpSessionLister
J'ai essayé d'utiliser une HttpSessionListerner
. La méthode appelée ayant la signature suivante:
public void sessionDestroyed(HttpSessionEvent se) {
}
Je n'ai pas pu rediriger vers une page spécifique. Lorsque je veux rediriger un utilisateur, j'utilise généralement la variable NavigationHandler
de la variable FacesContext
, mais dans ce cas, il n'y a pas de variable FacesContext
(FacesContext.getCurrentInstance()
renvoie null
).
Selon ce post , HttpListener ne peut pas rediriger l'utilisateur car il ne fait pas partie d'une requête.
Question
Quel est le meilleur moyen de résoudre ce problème? Que puis-je faire pour appliquer l’une des deux approches susmentionnées au travail?
Vous ne pouvez pas envoyer de réponse HTTP tant que le client n'envoie pas de requête HTTP. Aussi simple que cela. C'est comme ça que HTTP fonctionne. Internet aurait par ailleurs été très différent si un site Web était en mesure d'envoyer une réponse HTTP sans le vouloir, sans que le client ne l'ait demandé.
Une pulsation basée sur JavaScript et basée sur l'activité du client sur le clavier/la souris, telle que répondue ici , ou un en-tête méta refresh
ressemblant à la réponse ici serait la solution si vous avez essentiellement une seule page webapp (par conséquent, vous n'utilisez effectivement pas l'étendue de la session, mais celle de la vue), mais cela ne fonctionnera pas si la page est ouverte dans plusieurs onglets/fenêtres au cours d'une même session.
Websockets est en théorie la bonne solution pour envoyer quelque chose au client, mais cela nécessite à son tour une session active. Problème œuf de poulet. En outre, cela ne fonctionnerait pas dans les navigateurs plus anciens, qui étaient encore relativement utilisés, il devrait donc être simplement utilisé pour une amélioration progressive.
Votre meilleur pari est simplement de définir une page d'erreur qui traite du cas où l'utilisateur final appelle une action pendant que la session a expiré. Voir aussi javax.faces.application.ViewExpiredException: la vue n'a pas pu être restaurée .
Dans HttpSessionListerner, vous ne pouvez envoyer aucune réponse à l'utilisateur. La polling est un bon moyen d’atteindre cet objectif. Le navigateur envoie des requêtes HTTP à intervalles réguliers et reçoit immédiatement une réponse.
Il y a plusieurs façons de le faire:
Vous pouvez utiliser le vieux javascript pour interroger: Cela fonctionnera dans un environnement de navigateur croisé.
fonction refresh () {
// make Ajax call here, inside the callback call:
setTimeout(refresh, 5000);
// ...
}
// initial call, or just call refresh directly
setTimeout (actualisation, 5000);
Vous pouvez utiliser Web Sockets. La spécification de socket Web est présente sur le lien ci-dessous: