49 votes

Évitez le bouton de retour sur l'application Web JSF

Je montre des données TRÈS sensibles. Une fois que l'utilisateur s'est déconnecté de mon serveur, je ne veux pas qu'un autre utilisateur puisse voir les données sur le bouton Retour du navigateur.

Comment puis-je atteindre cet objectif?

82voto

BalusC Points 498232

Par défaut, le navigateur, le bouton de retour de ne pas envoyer une requête HTTP vers le serveur. Au lieu de cela, il récupère la page dans le cache du navigateur. C'est essentiellement inoffensif, mais en effet à confusion pour l'utilisateur final, car il a incorrectement pense que c'est vraiment à venir à partir du serveur.

Tout ce que vous devez faire est de demander au navigateur de ne pas mettre en cache les pages à accès restreint. Vous pouvez faire cela avec un simple filtre de servlet qui définit la réponse appropriée en-têtes:

@WebFilter
public class NoCacheFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        if (!request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) { // Skip JSF resources (CSS/JS/Images/etc)
            response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
            response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
            response.setDateHeader("Expires", 0); // Proxies.
        }

        chain.doFilter(req, res);
    }

    // ...
}

Pour le faire fonctionner sur tous les JSF demande, définir l'annotation suivante à la classe de filtre, en supposant que la valeur de l' <servlet-name> de la FacesServlet dans votre webapp de l' web.xml est facesServlet:

@WebFilter(servletNames={"facesServlet"})

Ou, pour le faire fonctionner sur un modèle d'URL, comme par exemple celui correspondant à la pages à accès restreint, par exemple, /app/*, /private/*, /secured/*, ou alors, ensemble l'annotation suivante à la classe de filtre:

@WebFilter("/app/*")

Vous pourriez même faire le même travail dans un filtre qui vérifie l'utilisateur connecté, si vous en avez déjà un.

Voir aussi:

10voto

Tony Points 2886

J'ai également trouvé une autre bonne solution.

Dans faces-config.xml, ajoutez

 <lifecycle>
    <phase-listener id="nocache">client.security.CacheControlPhaseListener</phase-listener>
</lifecycle>
 

Et implémentez la classe suivante:

 package client.security;

import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.servlet.http.HttpServletResponse;

@SuppressWarnings("serial")
public class CacheControlPhaseListener implements PhaseListener
{
    public PhaseId getPhaseId()
    {
        return PhaseId.RENDER_RESPONSE;
    }

    public void afterPhase(PhaseEvent event)        
    {
    }

    public void beforePhase(PhaseEvent event)
    {
       FacesContext facesContext = event.getFacesContext();
       HttpServletResponse response = (HttpServletResponse) facesContext
                .getExternalContext().getResponse();
       response.addHeader("Pragma", "no-cache");
       response.addHeader("Cache-Control", "no-cache");
       // Stronger according to blog comment below that references HTTP spec
       response.addHeader("Cache-Control", "no-store");
       response.addHeader("Cache-Control", "must-revalidate");
       // some date in the past
       response.addHeader("Expires", "Mon, 8 Aug 2006 10:00:00 GMT");
    }
} 
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X