Problema com Botão Voltar do Navegador e a Navegação Forward do JSF

4 respostas
M

Estou desenvolvendo uma aplicação Web utilizando JSF+Richfaces+Hibernate. No faces-config, nas navegações utilizo forward ou invésdo redirect.

Implementei um PhaseListener para fazer a autenticação e autorização do usuário, segue o código:

import javax.faces.application.NavigationHandler;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.servlet.http.HttpSession;

public class Autorizador implements PhaseListener {
    public void beforePhase(PhaseEvent event) {
        /*FacesContext fc = event.getFacesContext();
        System.out.println(event.getPhaseId());
        System.out.println(fc.getViewRoot().getViewId());*/
        FacesContext contexto = event.getFacesContext();
        String paginaAtual = contexto.getViewRoot().getViewId();
        boolean paginaLogin = (paginaAtual.lastIndexOf("/servidor/localizarServidor.jsp") > -1);
        HttpSession sessao = (HttpSession)contexto.getExternalContext().getSession(true);
        Object usuario = sessao.getAttribute("usuario");
        if (!paginaLogin && usuario == null) {
            NavigationHandler navegacao = contexto.getApplication().getNavigationHandler();
            navegacao.handleNavigation(contexto, null, "acesso");
        }
    }

    public void afterPhase(PhaseEvent event) {
        /*FacesContext fc = event.getFacesContext();
        System.out.println(event.getPhaseId());
        System.out.println(fc.getViewRoot().getViewId());*/        
    }

    public PhaseId getPhaseId() {
        return PhaseId.RENDER_RESPONSE;
    }
}

Implementei também um outro PhaseListener para fazer o controle de cache, segue o código:

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;

public class ControlaCache implements PhaseListener {
    public void beforePhase(PhaseEvent event) {
        FacesContext contexto = event.getFacesContext();
        HttpServletResponse response = (HttpServletResponse)contexto.getExternalContext().getResponse();
        response.setHeader("Expires", "-1");
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidade, proxy-revalidade, private, post-check=0, pre-check=0");
        response.setHeader("Pragma", "no-cache");        
    }

    public void afterPhase(PhaseEvent event) {
        
    }

    public PhaseId getPhaseId() {
        return PhaseId.RENDER_RESPONSE;
    }
}

Tenho uma tela de login.

Passando pela tela de login, tenho umas tela com abas(Dados do servidor, endereço, contato, dependente, instituidor(caso pensionista)).

Tenho uma tela final aonde o usuário confirma o cadastro. Nessa tela tem um: a4j:commandButton Confirmar que executa um action de um back bean, inserindo os dados, e no onclick abro um rich:modalPanel. Nesse rich:modalPanel tem um h:commandButton Fechar que executa um action de um back bean, pegando a sessao e invalidando-a, e no onclick fecho o rich:modalPanel e automaticamente volta para a tela de login. Até aqui tudo bem.

Agora vem o problema: quando clico no botão voltar do navegador, a tela final(confirmação do cadastro) é carregada, sendo que já invalidei a sessão.

Como resolver esse problema?

4 Respostas

vitenho

cara coloca os teus phaselisteners na PHASEID = RESTORE_VIEW e faz o checks de sessao antes de qualquer coisa

M

Como faço os checks de sessão?

vitenho
public void beforePhase(PhaseEvent ev) {
		String requestPath = ev.getFacesContext().getExternalContext().getRequestServletPath();
		if (requestPath.contains("report") || requestPath.contains("about"))
			return;
		FacesContextUtil faces = new FacesContextUtil();
		if (faces.getSession(false) == null) {// session acabou
			faces.sendRedirect("/home");
			faces.fc().responseComplete();
			return;
		}

		EmployeeBilly user = (EmployeeBilly) faces.getFromSessionMap(UserAccessor.USER_SESSION_ATTRIBUTE_NAME);

		synchronized (faces.getSession(true)) {
			if (user == null) {
				log.debug("iniciando o processo de login");
				UserSessionBean userBean = (UserSessionBean) faces.getFacesBean("userBean", UserSessionBean.class);
				if (userBean == null) {// panic : provavelmente nunca aconteça, se acontecer quer dizer que o IOC do jsf deu pau!
					faces.getSession(true).invalidate();
					faces.sendRedirect("/atlas");
				} else {
					String username = (String) faces.getFromSessionMap("username");
					String password = (String) faces.getFromSessionMap("password");
					EmployeeBilly login = null;
					try {
						password = new String(new BASE64Decoder().decodeBuffer(password));
					} catch (Exception e) {
						log.debug(e);
						// TODO: aqui temos q criar uma pagina de erro pra dizer pro user q o login falhou devido a um problema internoo na autenticacao
						faces.sendRedirect("/atlas");
						return;
					}
					log.debug("conferindo identidade do user: " + username);
					login = userBean.login(username, password);
					if (login != null) {
						faces.putOnSessionMap(UserAccessor.USER_SESSION_ATTRIBUTE_NAME, login);
						log.debug(new StringBuilder("user ").append(username).append(" logado com sucesso."));
					} else {
						faces.getSession(true).invalidate();
						faces.sendRedirect("/atlas");
						log.debug(new StringBuilder("user ").append(username).append(" falhou ao logar."));
					}
				}
			}
		}
	}

public PhaseId getPhaseId() {
		return PhaseId.RESTORE_VIEW;
	}
public class FacesContextUtil {

	public synchronized Object getFacesBean(String managedBeanName, Class<? extends Object> clazz) {
		if (managedBeanName == null)
			throw new IllegalArgumentException("o nome enviado para criação do bean é null");
		ValueExpression ve = fc().getApplication().getExpressionFactory().createValueExpression(fc().getELContext(), "#{" + managedBeanName + "}", clazz);
		return ve.getValue(fc().getELContext());
	}

	protected String getContextParam(String name) {
		return (String) fc().getExternalContext().getApplicationMap().get(name);
	}

	public void putOnSessionMap(String key, Object value) {
		synchronized (this) {
			sessionMap().put(key, value);
		}
	}

	public Object getFromSessionMap(String key) {
		synchronized (this) {
			return sessionMap().get(key);
		}
	}

	public Object removeFromSessionMap(String key) {
		synchronized (this) {
			return sessionMap().remove(key);
		}
	}

	public HttpSession session(boolean arg) {
		return (HttpSession) fc().getExternalContext().getSession(arg);
	}

	public void handleNavigation(String outcome) {
		fc().getApplication().getNavigationHandler().handleNavigation(fc(), null, outcome);
	}

	public void sendRedirect(String location) {
		try {
			response().sendRedirect(location);
			fc().responseComplete();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public FacesContext fc() {
		return FacesContext.getCurrentInstance();
	}

	private Map<String, Object> sessionMap() {
		fc().getExternalContext().getSession(false);
		return fc().getExternalContext().getSessionMap();
	}

	public HttpSession getSession(boolean create) {
		return (HttpSession) fc().getExternalContext().getSession(create);
	}

	private HttpServletResponse response() {
		return (HttpServletResponse) fc().getExternalContext().getResponse();
	}

}
M
vitenho:
public void beforePhase(PhaseEvent ev) {
		String requestPath = ev.getFacesContext().getExternalContext().getRequestServletPath();
		if (requestPath.contains("report") || requestPath.contains("about"))
			return;
		FacesContextUtil faces = new FacesContextUtil();
		if (faces.getSession(false) == null) {// session acabou
			faces.sendRedirect("/home");
			faces.fc().responseComplete();
			return;
		}

		EmployeeBilly user = (EmployeeBilly) faces.getFromSessionMap(UserAccessor.USER_SESSION_ATTRIBUTE_NAME);

		synchronized (faces.getSession(true)) {
			if (user == null) {
				log.debug("iniciando o processo de login");
				UserSessionBean userBean = (UserSessionBean) faces.getFacesBean("userBean", UserSessionBean.class);
				if (userBean == null) {// panic : provavelmente nunca aconteça, se acontecer quer dizer que o IOC do jsf deu pau!
					faces.getSession(true).invalidate();
					faces.sendRedirect("/atlas");
				} else {
					String username = (String) faces.getFromSessionMap("username");
					String password = (String) faces.getFromSessionMap("password");
					EmployeeBilly login = null;
					try {
						password = new String(new BASE64Decoder().decodeBuffer(password));
					} catch (Exception e) {
						log.debug(e);
						// TODO: aqui temos q criar uma pagina de erro pra dizer pro user q o login falhou devido a um problema internoo na autenticacao
						faces.sendRedirect("/atlas");
						return;
					}
					log.debug("conferindo identidade do user: " + username);
					login = userBean.login(username, password);
					if (login != null) {
						faces.putOnSessionMap(UserAccessor.USER_SESSION_ATTRIBUTE_NAME, login);
						log.debug(new StringBuilder("user ").append(username).append(" logado com sucesso."));
					} else {
						faces.getSession(true).invalidate();
						faces.sendRedirect("/atlas");
						log.debug(new StringBuilder("user ").append(username).append(" falhou ao logar."));
					}
				}
			}
		}
	}

public PhaseId getPhaseId() {
		return PhaseId.RESTORE_VIEW;
	}
public class FacesContextUtil {

	public synchronized Object getFacesBean(String managedBeanName, Class<? extends Object> clazz) {
		if (managedBeanName == null)
			throw new IllegalArgumentException("o nome enviado para criação do bean é null");
		ValueExpression ve = fc().getApplication().getExpressionFactory().createValueExpression(fc().getELContext(), "#{" + managedBeanName + "}", clazz);
		return ve.getValue(fc().getELContext());
	}

	protected String getContextParam(String name) {
		return (String) fc().getExternalContext().getApplicationMap().get(name);
	}

	public void putOnSessionMap(String key, Object value) {
		synchronized (this) {
			sessionMap().put(key, value);
		}
	}

	public Object getFromSessionMap(String key) {
		synchronized (this) {
			return sessionMap().get(key);
		}
	}

	public Object removeFromSessionMap(String key) {
		synchronized (this) {
			return sessionMap().remove(key);
		}
	}

	public HttpSession session(boolean arg) {
		return (HttpSession) fc().getExternalContext().getSession(arg);
	}

	public void handleNavigation(String outcome) {
		fc().getApplication().getNavigationHandler().handleNavigation(fc(), null, outcome);
	}

	public void sendRedirect(String location) {
		try {
			response().sendRedirect(location);
			fc().responseComplete();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public FacesContext fc() {
		return FacesContext.getCurrentInstance();
	}

	private Map<String, Object> sessionMap() {
		fc().getExternalContext().getSession(false);
		return fc().getExternalContext().getSessionMap();
	}

	public HttpSession getSession(boolean create) {
		return (HttpSession) fc().getExternalContext().getSession(create);
	}

	private HttpServletResponse response() {
		return (HttpServletResponse) fc().getExternalContext().getResponse();
	}

}

Não entendi muito o seu código. Se puderes enviar um projeto seu para eu dar um analisada, ficarei muito grato.

Criado 31 de julho de 2009
Ultima resposta 3 de ago. de 2009
Respostas 4
Participantes 2