Impedir que o usuário veja a página segura visitada anteriormente após o logout


99

Tenho o requisito de que o usuário final não possa voltar à página restrita após fazer logout / logout. Mas atualmente o usuário final é capaz de fazer isso pelo botão Voltar do navegador, visitando o histórico do navegador ou até mesmo reinserindo a URL na barra de endereços do navegador.

Basicamente, desejo que o usuário final não consiga acessar a página restrita de nenhuma forma após sair. Como posso conseguir isso da melhor maneira? Posso desativar o botão Voltar com JavaScript?


7
Use o padrão Post-request-get.Google it.

Respostas:


137

Você pode e não deve desabilitar o botão Voltar ou o histórico do navegador. Isso é ruim para a experiência do usuário. Existem hacks de JavaScript, mas eles não são confiáveis ​​e também não funcionarão quando o cliente tiver o JS desativado.

Seu problema concreto é que a página solicitada foi carregada do cache do navegador em vez de diretamente do servidor. Isso é essencialmente inofensivo, mas confuso para o usuário final, porque ele / ela pensa incorretamente que está realmente vindo do servidor.

Você só precisa instruir o navegador a não armazenar em cache todas as páginas JSP restritas (e, portanto, não apenas a página / ação de logout em si!). Desta forma, o navegador é forçado a solicitar a página do servidor em vez de do cache e, portanto, todas as verificações de login no servidor serão executadas. Você pode fazer isso usando um filtro que define os cabeçalhos de resposta necessários no doFilter()método:

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

    // ...
}

Mapeie isso Filterem um url-patternde interesse, por exemplo *.jsp.

@WebFilter("*.jsp")

Ou se você deseja colocar essa restrição apenas em páginas seguras, você deve especificar um padrão de URL que cubra todas essas páginas seguras. Por exemplo, quando eles estão todos na pasta /app, você precisa especificar o padrão de URL de /app/*.

@WebFilter("/app/*")

Além disso, você pode fazer esse trabalho da mesma Filterforma que verifica a presença do usuário conectado.

Não se esqueça de limpar o cache do navegador antes de testar! ;)

Veja também:


2
Às vezes, isso não é suficiente, lembro-me de ter esse problema. O navegador apenas se lembra da última página. Mas pode ter sido o IE6, não me lembro :)
Bozho

3
@Bozho: Ou você forneceu um conjunto incompleto de cabeçalhos ou o navegador ainda tem a página em seu cache.
BalusC de

1
@Chris: funciona para mim com Firefox e todos os outros navegadores. Seu problema é causado em outro lugar. Talvez você tenha esquecido de limpar algum cache? Ou esses cabeçalhos são definidos nas respostas erradas?
BalusC

@BalusC Eu criei uma classe Filter separada para substituir o doFilter()método. Quando pressiono o botão de logout, ele é redirecionado para um servlet onde invalido a sessão. Não tenho certeza de como o doFilter()método entra em jogo aqui. Você pode me dizer como implementar isso? Como em, as etapas corretas a seguir. Obrigado.
Anjan Baradwaj

Funcionou bem para mim. Testado após sendRedirect(...)e forward().
Hal50000

5

* .jsp no padrão de URL não funcionará se você encaminhar uma página. Tente incluir seu servlet também .. isso tornará seu aplicativo seguro contra este problema do botão Voltar.


2

A maneira mais simples de fazer isso sem desativar o botão de retorno do navegador é adicionar este código ao page_loadevento da página que você não deseja que o usuário volte depois de sair:

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

6
Embora sua resposta seja útil, poste a resposta que se relaciona com a linguagem de programação de OP de sua escolha. Sua solução C # não ajudará no projeto Java EE do OP.
Buhake Sindi

0

Você pode tentar dizer ao navegador para não armazenar em cache a página inicial (usando os cabeçalhos apropriados - Expires, Cache-Control, Pragma). Mas não é garantido que funcione. O que você pode fazer é fazer uma chamada ajax para o servidor no carregamento da página para verificar se o usuário está logado e, se não, redirecionar.


13
Mas se uma mente má desabilita o JavaScript, isso não funciona e ele verá a página mesmo assim.
acme

0

A maneira correta de fazer isso é adicionar o

Vary: Cookie

cabeçalho em páginas protegidas. Quando o usuário fizer logout, limpe o cookie da sessão. Então, quando eles navegarem de volta após o logout, o cache do navegador falhará. Isso também tem a vantagem de não anular completamente o cache.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.