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?
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?
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.
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 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.