Empêcher l'utilisateur de voir la page sécurisée précédemment visitée après la déconnexion

99

J'ai l'obligation pour l'utilisateur final de ne pas pouvoir revenir à la page restreinte après la déconnexion / déconnexion. Mais actuellement, l'utilisateur final peut le faire par le bouton de retour du navigateur, en visitant l'historique du navigateur ou même en entrant à nouveau l'URL dans la barre d'adresse du navigateur.

Fondamentalement, je souhaite que l'utilisateur final ne puisse en aucun cas accéder à la page restreinte après la déconnexion. Comment puis-je y parvenir au mieux? Puis-je désactiver le bouton de retour avec JavaScript?

Raaz
la source
7
Utilisez le modèle Post-request-get.

Réponses:

137

Vous pouvez et ne devez pas désactiver le bouton de retour ou l'historique du navigateur. C'est mauvais pour l'expérience utilisateur. Il existe des hacks JavaScript, mais ils ne sont pas fiables et ne fonctionneront pas non plus lorsque le client a désactivé JS.

Votre problème concret est que la page demandée est chargée depuis le cache du navigateur au lieu d'être directement depuis le serveur. Ceci est essentiellement inoffensif, mais en effet déroutant pour l'utilisateur final, car il / elle pense à tort que cela vient vraiment du serveur.

Il vous suffit d'indiquer au navigateur de ne pas mettre en cache toutes les pages JSP restreintes (et donc pas seulement la page / l'action de déconnexion elle-même!). De cette façon, le navigateur est obligé de demander la page au serveur plutôt qu'à partir du cache et donc toutes les vérifications de connexion sur le serveur seront exécutées. Vous pouvez le faire en utilisant un filtre qui définit les en- têtes de réponse nécessaires dans la doFilter()méthode:

@WebFilter
public class NoCacheFilter implements Filter {

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

        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);
    }

    // ...
}

Mappez ceci Filtersur un point url-patternd'intérêt, par exemple *.jsp.

@WebFilter("*.jsp")

Ou si vous souhaitez mettre cette restriction sur les pages sécurisées uniquement, vous devez spécifier un modèle d'URL qui couvre toutes ces pages sécurisées. Par exemple, lorsqu'ils sont tous dans le dossier /app, vous devez spécifier le modèle d'URL de /app/*.

@WebFilter("/app/*")

De plus, vous pouvez effectuer ce travail de la même manière Filterque lorsque vous vérifiez la présence de l'utilisateur connecté.

N'oubliez pas de vider le cache du navigateur avant de tester! ;)

Voir également:

BalusC
la source
2
Parfois, cela ne suffit pas, je me souviens avoir eu un tel problème. Le navigateur se souvient simplement de la dernière page. Mais c'était peut-être IE6, je ne me souviens pas :)
Bozho
3
@Bozho: Soit vous avez fourni un ensemble d'en-têtes incomplet, soit le navigateur a toujours la page dans son cache.
BalusC
1
@Chris: fonctionne pour moi avec Firefox et tous les autres navigateurs. Votre problème est causé ailleurs. Peut-être avez-vous oublié de vider du cache? Ou ces en-têtes sont définis sur les mauvaises réponses?
BalusC
@BalusC J'ai créé une classe Filter distincte pour remplacer la doFilter()méthode. Lorsque j'appuie sur le bouton de déconnexion, il est redirigé vers un servlet où j'invalide la session. Je ne sais pas comment la doFilter()méthode entre en jeu ici. Pouvez-vous me dire comment mettre en œuvre cela? Comme dans, les étapes correctes à suivre. Merci.
Anjan Baradwaj
A bien fonctionné pour moi. Testé après les deux sendRedirect(...)et forward().
Hal50000
5

* .jsp dans le modèle d'URL ne fonctionnera pas si vous transférez une page. Essayez également d'inclure votre servlet. Cela sécurisera votre application de ce problème de bouton de retour.

Sathyan
la source
2

Le moyen le plus simple de le faire sans désactiver le bouton de retour du navigateur consiste à ajouter ce code à l' page_loadévénement de la page sur laquelle vous ne souhaitez pas que l'utilisateur revienne après la déconnexion:

if (!IsPostBack)
    {
        if (Session["userId"] == null)
        {
            Response.Redirect("Login.aspx");
        }
        else
        {
        Response.ClearHeaders();
        Response.ClearContent();
        Response.Clear();
        Session.Abandon();
        Session.Remove("\\w+");
        Response.AddHeader("Cache-Control", "no-cache, no-store, max-age = 0, must-revalidate");
        Response.AddHeader("Pragma", "no-cache");
        Response.AddHeader("Expires", "0");
        }
    }
Achraf Abusada
la source
6
Bien que votre réponse soit utile, veuillez poster la réponse qui se rapporte au langage de programmation choisi par l'OP. Votre solution C # n'aidera pas dans le projet Java EE de l'OP.
Buhake Sindi
0

Vous pouvez essayer de dire au navigateur de ne pas mettre en cache la page d'accueil (en utilisant les en-têtes appropriés - Expire, Cache-Control, Pragma). Mais il n'est pas garanti que cela fonctionne. Ce que vous pouvez faire, c'est faire un appel ajax au serveur lors du chargement de la page pour vérifier si l'utilisateur est connecté, et sinon, rediriger.

Bozho
la source
13
Mais si un esprit pervers désactive JavaScript, cela ne fonctionne pas et il verra quand même la page.
acme
0

La bonne façon de procéder est d'ajouter le

Vary: Cookie

en-tête sur les pages sécurisées. Lorsque l'utilisateur se déconnecte, effacez son cookie de session. Ensuite, lorsqu'ils reviennent après la déconnexion, le cache du navigateur manquera. Cela présente également l'avantage de ne pas vaincre complètement la mise en cache.

Dan
la source