Após Logout com Spring Security é possível ver páginas anteriores pelo botão Voltar

Olá pessoal, boa noite!

Meu Post anterior foi fechado sem resposta, então vamos novamente …
Estou praticando meus estudos com desenvolvimento Web e tenho um problema após o Logout do Spring Security no meu projeto (JSF, Primefaces, Hibernate, Spring e Spring Security, Tomcat 7).
Depois de acionar o Link de sair na página, o Spring sai e redireciona para a página de Login novamente.
Mas se clicar no botão Voltar do navegador, da para ver o conteúdo das páginas anteriores.
Se clicar em qualquer botão ele devolve para a página de Login novamente indicando que a sessão já foi encerrada, mas ainda permite ver as páginas acessadas anteriormente.
Já coloquei as propriedades EXPIRES e PRAGMA na Tag META mas não funcionou.

<meta http-equiv="EXPIRES" content="0" />
<meta http-equiv="pragma" content="nocache" />

Alguém já passou por esse problema que possa me ajudar, por favor?

1 curtida

O problema é o cache da página… Já tentou acrescentar

<meta Http-Equiv="Cache-Control" Content="no-cache">
1 curtida

Obrigado pelo retorno @Logusmao, mas tentei como você sugeriu e o problema ainda persiste.
O head das minhas páginas de template estão assim agora:

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Expires" content="0" />
<meta http-equiv="Pragma" content="nocache" />
<meta http-equiv="Cache-Control" content="no-cache" />
1 curtida

Você não deve estar fazendo o logout corretamente, faço como abaixo e não tenho este problema :

@RequestMapping(value = "/logout", method = RequestMethod.GET)
    public String logout(HttpServletRequest request, HttpServletResponse response) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null) {
            new SecurityContextLogoutHandler().logout(request, response, auth);
        }
        return "home/login";
    }

Boa tarde @edulemos, obrigado pela dica, mas o problema ainda continua.

O meu logout estava no padrão do Spring.
#{request.contextPath}/j_spring_security_logout

Mesmo depois que implementei o método de saída que sugeriu no meu ManagedBean, o logout continua funcionando certinho por ele também, mas ainda assim o Voltar do navegador deixa passar pelas páginas anteriores.

Ainda junto ao seu método coloquei mais algumas coisas para forçar como abaixo e nada.

HttpSession session = (request).getSession();
session.invalidate();
		
SecurityContextHolder.clearContext();

Desabilitei o Cache da página na configuração da hospedagem também e nada.
O comportamento é o mesmo tanto no localhost de desenvolvimento quando no ambiente de produção do Datacenter.

Alguma outra sugestão?

Olá,

Veja: http://stackoverflow.com/questions/11050840/call-to-j-spring-security-logout-not-working

Atenciosamente.

P.S.: é um chute/adivinhação, baseado nas poucas informações que você forneceu.

Tenta usar um filtro do Tipo:

@WebFilter(urlPatterns = "/pages/*")
public class FiltroSeguranca implements Filter {

    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        HttpSession sessao = httpRequest.getSession();
        String contextPath = httpRequest.getContextPath();

        LoginController login = (LoginController) sessao.getAttribute("loginController");

        if (login == null || login.getUsuario() == null || login.getUsuario().getCpf() == null) {
            httpResponse.sendRedirect(contextPath + "/");
        }

        chain.doFilter(request, response);
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
    }

}

e no logout:

FacesContext.getCurrentInstance().getExternalContext().invalidateSession();

Olá,

Sim, conforme você mostrou e abaixo também, para invalidar uma sessão do JSF utiliza-se: FacesContext.getCurrentInstance().getExternalContext().invalidateSession();

Bom dia!

Obrigado @edulemos e @cviniciusm pelo apoio.
Tentei as soluções propostas por vocês e também não havia dado certo.
Mas pelo caminho delas achei o que precisava e agora está funcionando.

Até deixei de utilizar o logout customizado e voltei o original do Spring Security.
Dessa forma tive que implementar esse filtro que força o não armazenamento do chace do navegador.
Não sei porque, mas de alguma forma parece que essa mesma configuração que já tinha no head das páginas não estava funcionando pelo jeito. Até tirei de lá.
Meu filtro ficou assim:

@WebFilter("/*")
public class CacheFilter implements Filter{
	
	@Override
	public void doFilter(ServletRequest servletRequest, 
			ServletResponse servletResponse, 
			FilterChain chain)
			throws IOException, ServletException {
		
		HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
		httpResponse.setHeader("Cache-Control", "no-cache,no-store,must-revalidate"); // HTTP 1.1
		httpResponse.setHeader("Pragma", "no-cache"); // HTTP 1.0
		httpResponse.setDateHeader("Expires", 0); // Proxies
		
		SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
		Date hora = Calendar.getInstance().getTime();
		System.out.println(sdf.format(hora) + " - Passou no CacheFilter");
		
		chain.doFilter(servletRequest, servletResponse);
	}
	
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {}
	
	@Override
	public void destroy() {}
}

Obviamente perdi performance porque sem o cache ele faz toda hora a requisição para o provedor.
Mas como a aplicação é pequena, vai atender o quesito de segurança.

Conforme for estudando mais, espero achar uma solução melhor mais para frente que não custe desempenho.

Olá,

Os cursos de JavaSever Faces no Alura mostram como implementar autenticação utilizando MySQL e JSF Phase Listener. E funciona corretamente. Quando o usuário faz logon, o objeto desse usuário é salvo na sessão; antes de uma página ser exibida o phase listener verifica se o objeto do usuário existe, em caso afirmativo mostra a página, caso contrário mostra a página de login. Não adianta usar os botões de ir para a próxima página ou voltar.

E o Java EE provê “Container Managed Authentication” que facilita a autenticação e autorização.

Veja: http://docs.oracle.com/javaee/7/tutorial/security-webtier.htm#BNCAS

Assim, suponho que você não esteja fazendo a integração correta de JSF com Spring Security.

Veja o projeto JoinFaces (ex-projeto JSF Spring Boot) que tem um exemplo que mostra a integração da JSF + Spring Boot + Spring Security, com autenticação e autorização.

Po favor, veja o seguinte exemplo: https://github.com/joinfaces/joinfaces-example

Atenciosamente.

Olá,

Um outro exemplo de autenticação: