Filtrando requisições em JSF com PhaseListener

Antigamente a forma mais comum para se criar uma forma de verificar a autorização das requisições feitas para determinado recurso de uma aplicação web era utilizando um filtro (Filter). Porém em Java Server Faces (JSF), podemos realizar esta tarefa de uma outra forma mais integrada, utilizando a interface PhaseListener.

Esta interface disponibiliza 3 métodos:

1
2
3
void afterPhase(PhaseEvent event);
void beforePhase(PhaseEvent event);
PhaseId getPhaseId();

No exemplo, irei demonstrar como utilizar o método afterPhase que tem por finalidade fazer o tratamento de uma notificação assim que o processamento de uma determinada fase acabar de ser concluída.

A idéia principal do listener será verificar se existe um atributo de sessão chamado “currentUser” que será uma instância de um objeto User e este representará o usuário logado na aplicação. Caso este atributo exista, o listener deixa o ciclo da pagina seguir, mas caso o atributo não exista o ciclo será interrompido e redirecionado para a página de login.

Também terá uma verificação para não fazer nenhuma verificação caso a página atual da requisição seja a página de login.

Aqui temos o código do PhaseListener:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.rodrigolazoti.filter;

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 AuthorizationListener implements PhaseListener {

  public void afterPhase(PhaseEvent event) {

    FacesContext facesContext = event.getFacesContext();
    String currentPage = facesContext.getViewRoot().getViewId();

    boolean isLoginPage = (currentPage.lastIndexOf("login.jsf") > -1);
    HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(true);
    Object currentUser = session.getAttribute("currentUser");

    if (!isLoginPage && currentUser == null) {
      NavigationHandler nh = facesContext.getApplication().getNavigationHandler();
      nh.handleNavigation(facesContext, null, "loginPage");
    }
  }

  public void beforePhase(PhaseEvent event) {
  }

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

}

Note que o redirecionamento é feito por uma navegação configurada no arquivo faces-config.xml. Esta configuração é algo como:

1
2
3
4
5
6
7
<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>

Também deve-se incluir o listener no faces-config.xml:

1
2
3
<lifecycle>
  <phase-listener>com.rodrigolazoti.filter.AuthorizationListener</phase-listener>
</lifecycle>

E com isso já se tem um PhaseListener funcionando e filtrando as requisições da aplicação.


comments powered by Disqus