Evitar acesso via url à páginas restritas em JSF

Boa noite, pessoal…

Eu pesquisei feito louco, mas não achei uma solução para o meu problema. É o seguinte:

  • Eu tenho uma página de Login, onde o administrador do site se loga, e manipula cadastros etc…;
  • Já tratei a parte de Login, onde meu backing-bean contido no botão de login retorna null para acesso não autorizado, e “enter” para acesso autorizado;
  • Mas eu gostaria de evitar que sem logar, um usuário pudesse entrar na minha página de adminitrador atraves da url…

Ex:

Página de login é: http://localhost:8080/MyApplication/login.xhtml
Página do admin: http://localhost:8080/MyApplication/admin.xhtml

Ele dando entrada no navegador pela segunda url, consegue acessar, sem precisar logar, a minha página de administrador…

As soluções que encontro, ao meu entender, não funcionam, pois elas só entram em ação durante um request, e no meu caso, é apenas uma acesso via url. Eu tenho um método no meu backing-bean que verifica se o usuário está na sessão (logado). Mas como eu faria para implementá-lo automaticamente, ou seja, toda vez que minha página é requisitada, ela teria que automaticamente, executar esse meu método, e assim me informar se o usuário está ou não logado. Mas para isso eu teria que usar um commandButton, e não é bem essa a solução.

Alguém poderia dar uma mãozinha? :smiley:

Boa noite, cara eu costumo utilizar um PhaseListener para esses casos, dai sempre que uma página é chamada ele veriifca se o usuário está logado se sim, manda para a pagina senão manda para login, com isso você pode também saber se é um adm(até hoje não fiz isso, pois uso outra coisa para controlar páginas que o usuário pode ou não accessar) ou não ai fazer o que deseja com a chamada…

[]'s

se isso abaixo te ajudar maravilha…

no faces config faço isso:

         <lifecycle>
		<phase-listener>br.com.cotacao.filter.Autorizador</phase-listener>
	</lifecycle>

a classe

package br.com.cotacao.filter;

import javax.el.ELResolver;
import javax.faces.application.FacesMessage;
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 br.com.cotacao.handlers.LoginHandler;
import br.com.cotacao.util.MensagensUtil;

public class Autorizador implements PhaseListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public static final String loginPage = "/paginas/login.jsp";

	@Override
	public void afterPhase(PhaseEvent event) {
		FacesContext fc = event.getFacesContext();

		if (fc.getViewRoot().getViewId().equals(loginPage)) {
			return;
		}

		ELResolver elResolver = fc.getApplication().getELResolver();
		LoginHandler loginHandler = (LoginHandler) elResolver.getValue(fc
				.getELContext(), null, "loginHandler");

		if (loginHandler == null || !loginHandler.isLogado()) {
			FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
					MensagensUtil.getMensagem("accessDenied"), MensagensUtil
							.getMensagem("accessDenied"));
		
			fc.addMessage("formLogin", message);

			NavigationHandler nav = fc.getApplication().getNavigationHandler();
			nav.handleNavigation(fc, null, "login");
			fc.renderResponse();
		}

	}

	@Override
	public void beforePhase(PhaseEvent arg0) {

	}

	@Override
	public PhaseId getPhaseId() {
		return PhaseId.RESTORE_VIEW;
	}

}

alberto_ribeiro

Cara, sua resposta não foi bem o que eu queria, pois tem alguns comandos que eu não entendi:

ELResolver elResolver = fc.getApplication().getELResolver();  
LoginHandler loginHandler = (LoginHandler) elResolver.getValue(fc.getELContext(), null, "loginHandler");  

E você importou duas classes externas, nas quais eu não faço a menor idéia de como foram implementadas :roll:

import  br.com.cotacao.handlers.LoginHandler;  
import br.com.cotacao.util.MensagensUtil;

Mas o importante é que seu código me ajudou a formular outro que vi nesse link: http://www.rodrigolazoti.com.br/pt/2008/09/01/filtrando-usuarios-logados-em-jsf-com-phaselistener/

E assim eu consegui fazer uma lógica que eu entendesse e deu certo aqui :lol:

Eu estava achando que o PhaseListener só executava após o usuário dar um submit em algum formulário :lol:
Mas vi que me enganei… subestimei o JSF? :shock:

Bem, aqui está minha classe que verifica se a página requisitada pode ser acessada. Nesse caso, só dá certo com uma página. Para fazer com mais, eu precisaria de
armazenar todas em um vetor, fazer um forit para um objeto, e comparar se esse objeto não é nulo lá no meu if? ou tem alguma maneira mais fácil?

package meuProjeto.jsf;

import meuProjeto.beans.Admin;
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.HttpServletRequest;

public class Autorizador implements PhaseListener{

    public void afterPhase(PhaseEvent event) {
        FacesContext fc = event.getFacesContext(); //pego o contexto do Faces
        String currentPage = fc.getViewRoot().getViewId(); // armazeno numa String o id da minha página que está sendo requisitada

        boolean isRequisitedPage = (currentPage.lastIndexOf("/admin.xhtml") > -1); // verifico se a página requisitada é a admin
        HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest(); // instancio um request
        Admin admin = (Admin)request.getSession().getAttribute("admin"); // pego o meu objeto admin da sessão

        if(isRequisitedPage && admin == null){ //verifico se a página requisitada é a admin
            NavigationHandler nh = fc.getApplication().getNavigationHandler(); // instancio um objeto de navegação
            nh.handleNavigation(fc, null, "loginPage"); // passo o contexto do Faces, null para minha action, e loginPage como from-outcome
            fc.renderResponse(); // chamo a última fase do ciclo de vida
        }
    }

    public void beforePhase(PhaseEvent event) {
    }

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

}

Aqui parte do faces-config:

<navigation-rule>
        <from-view-id>/*</from-view-id>
        <navigation-case>
            <from-outcome>loginPage</from-outcome>
            <to-view-id>/login.xhtml</to-view-id>
        </navigation-case>
</navigation-rule>

<application>
        <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
</application>

Valeu, muito obrigado mesmo… :smiley:

Já pensou em Sessions
Ex: de Session:
Session em JSP

vlw