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?

Controle Transaciona Programatico

OO no mundo real: evite vazamento de conexões com controle transacional programático

No último Javou (evento da JavaCE) o prof. Alexandre Martins comentou na sua palestra que um dev junior conseguiu derrubar por alguns minutos o sistema de previdência social da Dataprev. Estou falando do principal sistema da empresa… muito louco não?

Sabe como? Ele esqueceu de colocar essa linha de código aqui:

conexao.close();  // fecha conexão com o banco

Simmm! Ele esqueceu de fechar uma conexão com o banco de dados! Se você não sabe, uma conexão é um recurso muito caro e, para piorar, é muito limitado; todo banco tem um limite de conexões que podem ser abertas, se esse limite estourar já era, a aplicação não consegue mais conversar com o banco!

(Eu nem culpo esse dev junior, até porque eu já fiz algo parecido em alguns sistemas… mas não conta pra ninguém, tá?)

Mas como ele poderia ter evitado?

A boa prática diz que todo recurso caro que for aberto deve sempre ser fechado quando não for mais utilizado. Uma boa maneira de fazer isso é através do bloco try-catch-finally do Java:

Connection conexao = null;
try {
    conexao = ConnectionFactory.getConnection();
    // logica de negócio

} catch (SQLException e) {
    // trata erro
} finally {
    conexao.close(); // fecha conexão com o banco
}

O problema é que repetir esse código em todo o sistema é muito frágil, cedo ou tarde alguém esquece e termina com o sistema fora do ar. Aí já viu né, é justa causa…

E se eu te dissesse que tem uma maneira mais elegante de resolver isso usando OO? É o que chamamos de controle transacional programático e traz diversos benefícios para qualquer sistema, entre eles a garantia que toda conexão com o banco é fechada!

Pra te ajudar a entender do que estou falando, eu bloguei sobre o assunto:

[Post] Controle Transacional Programático em Sistemas Legados

Após ler esse artigo eu te garanto que você vai levar o controle de conexões e transações na sua aplicação mais a sério, seja seu sistema legado ou mais moderno com JPA e Hibernate.

TriadWorks: Deploy Automatizado

Aprenda como Automatizar seu Deploy em 15min…

Você faz deploy da sua aplicação manualmente? Em produção? Não cara, não faz isso.

Você sabe que esse processo manual cedo ou tarde vai te trazer uma grande dor de cabeça, né? Qualquer tarefa manual, repetitiva e feita por um ser humano tende a não dar certo.

A melhor forma de resolver isso é automatizando: desde build até o processo de deploy. Automatizar o deploy não precisa ser algo difícil nem sofisticado, você consegue resolver isso com 2 passos simples:

  1. liste todos os passos do deploy num arquivo TXT;
  2. transforme essa lista num script executável;

Pronto! A partir de agora você tem um processo de deploy automatizado sem firulas! Não sabe escrever o script? Não te preocupas, eu te ensino como fazer nesse novo post no blog:

[Post] Deploy Automatizado: feito é melhor que perfeito

Deploy deve ser simples e executado com frequência, dessa forma você diminui os riscos a cada nova versão da sua aplicação.

E aí, o que achou? Será que você consegue aplicar o script do post no seu trabalho? Comenta lá, deixa eu saber!