computer_security_stock_image-100582931-orig

Segurança: não coloque o usuário logado no controller

É incrível como você aprende com a experiência. Saca só a jornada que tive para aprender a implementar segurança na web…

Quando comecei minha carreira como programador, lá por volta de 2005, e tive que implementar meu primeiro controle de acesso eu só sabia fazer isso de uma forma, e era jogando os dados do usuário logado diretamente na sessão:

public String logar(String login, String senha) {
    Usuario usuario = this.autentica(login, senha);
    if (usuario != null) {
        Session sessao = this.getSession();
        sessao.setAttribute("usuarioLogado", usuario); // coloca usuario na sessão
        return "/home.jsp";
    }
    return "/login.jsp";
}

Um dos problemas chatos dessa abordagem é que eu tinha que ficar testando se o usuário existia na sessão antes de fazer minhas lógicas de segurança – um saco! Era algo muito parecido com o código abaixo:

Usuario usuario = sessao.getAttribute("usuarioLogado");
if (usuario != null && usuario.getTipo() == ADMIN) {
    // logica de negocio...
}

Daí o tempo passou e depois aprendi outra forma mais esperta, que era deixando o usuário logado dentro do controller, no caso do JSF eu deixava dentro do managed bean:

@ManagedBean
@SessionScoped // managed bean na sessão
public class LoginBean {
    // outros atributos
    private Usuario usuarioLogado;

    public String logar() {
        // lógica para autenticar usuário e setar atributo usuarioLogado
    }
}

Resolveu? Ahhh… não!

Essa abordagem também trazia problemas sutis que eu levei alguns anos pra enxergar, apesar de sutis eles foram bem sérios e sobrecarregaram a memoria do servidor. Por esse motivo, para você não cometer os erros que eu cometi, eu bloguei sobre como representar o usuário logado no meu sistema mas desta vez tirando proveito da OO de verdade:

[Post] OO na prática: representando usuário logado no sistema

Após ler o post sobre essa prática você vai se perguntar porque diabos você não fez isso antes, afinal de contas, basta usar OO para modelar conceitos em objetos, que é algo que fazemos dia a dia para nossas entidades mas que ignoramos quando falamos de segurança.

E aí, como você tem feito pra guardar os dados do usuário logado?

CDI: Não use @Inject e @ManagedBean nas suas classes

Algumas semanas atrás tive uma experiência bem estressante e chata ao misturar as anotações do JSF com as anotações do CDI. Apesar de saber que EM TEORIA eu não deveria fazer isso eu acabei fazendo e percebendo o problema NA PRÁTICA.

O problema ocorria quando minha página processava uma EL (Expression Language) que apontava para um managed bean anotado com @ManagedBean e tinha suas dependências injetadas pelo CDI através da anotação @Inject… nesse momento a injeção não ocorria. Sendo mais específico, simplesmente o container (qual deles? JSF ou CDI?) injetava null no atributo da classe. O código era semelhante a este:

@ManagedBean
public class AlunosBean {

    @Inject
    private AlunosDao dao;

}

A coisa fica ainda mais feia quando misturava os escopos do CDI com o escopos do JSF. Imagina um managed bean sendo instanciado trocentas vezes? Pois é…

Depois de muito ler e discutir com amigos que sacam mais de CDI do que eu, como o Raphael Lacerda e Daniel Cunha, eu percebi que NÃO era uma boa prática misturar as anotações. Para você entender mais a fundo do que estou falando eu bloguei no blog da TriadWorks sobre isso. Você pode ler o post completo no link abaixo:

>>> NÃO misture anotações do JSF com as anotações do CDI

O post fala um pouco sobre meu problema e de quebra ensina como você pode migrar seus managed beans do JSF para beans do CDI. Onde com certeza essa é a melhor escolha que você poderia tomar.

Enfim, uma experiência interessante que quis compartilhar.

Projetos de estudo para JSF2, Spring e Hibernate

Quem está iniciando a desenvolver aplicações Web em Java, após estudar vários frameworks de forma isolada, acaba tendo algum tipo de dificuldade para integrar 2-4 frameworks a fim de ter uma arquitetura inicial de desenvolvimento.

Existem várias discussões sobre qual modelo seguir, JavaEE (CDI, EJB etc) com um servidor de aplicação robusto ou Spring com o bom e velho Tomcat. Decidir qual o melhor modelo envolve inúmeras variáveis que dependem do projeto e da equipe.

Deixando um pouco de lado essa discussão, eu pretendo enumerar alguns projetos que nós da TriadWorks utilizamos em nossos cursos e treinamentos. Os projetos são construídos durante os cursos de JSF (1.2 e 2.0), Spring e Hibernate pelos próprios alunos seguindo o método de ensino bottom-up.

Todos os projetos estão disponibilizados no GitHub a fim de facilitar o estudo, visualização do código e a atualização periódica. Segue abaixo os projetos:

  1. jsf-issuetracker – Projeto de uma aplicação de Issue Tracker com JSF 2.x, Spring 3.x e Hibernate 3.6.x (JPA2).
  2. jpa-issuetracker – Projeto de uma aplicação de Issue Tracker modelada com Hibernate 3.6.x (JPA2) e Spring 3.x.
  3. jsf-loja – Projeto de uma aplicação de Loja Virtual com JSF 1.2, Spring 3.x e Hibernate 3.5.x, além do uso de teste de unidade e integração.

Com a facilidade de compartilhar e colaborar código provinda do GitHub o projeto original jsf-issuetracker possui algumas versões (forks) bem interessantes feitas pelo Rafael Pestano, criador do Conventions Framework. O Rafael migrou o projeto original para tecnologias como CDI, EJB 3.1, CODI, Primefaces-Extensions e o próprio Conventions.

  1. jsf-issuetracker-cdi (OpenWebBeans) – idêntico ao projeto original, porém utilizando CDI com OpenWebBeans.
  2. jsf-issuetracker-cdi (Weld) – idêntico ao anterior, porém utilizando CDI com Weld.
  3. jsf-issuetracker-cdi-conventions (OpenWebBeans) – versão utilizando CDI com OpenWebBeans e Conventions Framework.
  4. jsf-issuetracker-cdi-conventions (Weld) – versão utilizando CDI com Weld e Conventions Framework.
  5. jsf-issuetracker-cdi-jboss (Weld) – versão utilizando CDI com Weld, EJB 3.1 e Conventions Framework na qual roda num JBoss AS 7. Esta versão possui uma aplicação demo hospedada no OpenShift.

São 6 (seis) versões do mesmo projeto com tecnologias diferentes que rodam em Tomcat e JBoss AS 7, ou seja, não há desculpas para não estudar e avaliar qual delas se encaixa melhor no seu projeto ou equipe.

O repositório de cada projeto possui um README que ajudará a configurar e fazer o deploy da aplicação. Se o README não estiver claro o suficiente ou mesmo incorreto, por favor, deixe-me saber que tentarei melhora-lo com a sua ajuda.

Caso tenha interesse ou alguma dúvida nos cursos e treinamentos da TriadWorks, por favor, deixe-nos saber.