Sempre nos exemplos que vejo de camadas de persistência, conexão com banco de dados, etc. encontro um único usuário sendo usado, geralmente em um arquivo .properties, algo como:
Arquivo de propriedades do banco de dados
jdbc.url = xxxxxxxxxxx;
jdbc.username = user
jdbc.password = password
Classe responsável por fazer a conexão com o banco
Connection con = DriverManager.getConnection(url, username, password);
Onde “url”, “username” e “password” são fixos (no arquivo de propriedades) e todos os usuários utilizam um pool para esta conexão.
Isso é excelente quando é possível fazer este pool de conexões, mas quando é uma exigência que o usuário que está acessando o banco seja um usuário do banco de dados usado, como proceder?
Sei que não é recomendado, mas é uma exigência para permitir que o banco realize auditoria das operações.
Sei também que as operações podem ser auditadas utilizando a aplicação, mas isso não é o que o cliente deseja.
Então como autenticar o usuário de uma aplicação, usando os usuários do banco em um ambiente web, usando servlets?
Gostaria de “ouvir” a opinião de vocês sobre isso e discutir sobre uma solução.
Atualmente uso o iBatis, mas pretendo migrar para o Hibernate ou JPA.
Nunca fiz isso, mas la vai uma idéia
Faça com que o usuario digite o id/password. Tente fazer a conexão com esse ID/Password, ai caso dê erro, uma exception será lançada. Tente tratar essa exception e verificar se foi erro de id/senha inválidos.
A solução que você apresentou está correta mas em um ambiente web, nos exemplos que vejo, a validação do usuário e senha é realizado apenas uma vez no momento da criação da entidade que vai fazer o gerenciamento/conexão com o banco.
Esta única conexão (com usuário e senha fixos) é compartilhada por todas as requisições que fazem acesso ao banco de dados e é esse o ganho obtido por um pool de conexões, já que abrir e fechar uma conexão é um processo caro no consumo de CPU, memória, etc.
Neste cenário, após o primeiro usuário entrar com um id/senha válidos, todos os outros reutilizariam esta conexão através do pool.
No meu caso o que importa não é a performace das operações no banco, que justifica o uso de um pool de conexões, pensando em um cenário típico de aplicações web que podem ter centenas ou mesmo milhares de usuários simultaneos.
No meu caso é mais importante ter a auditoria realizada pelo banco de dados, com cada usuário tendo uma conexão própria. Mesmo que isso venha a ter perda de performace em um primeiro momento.
Desta forma após o usuário ser autenticado pelo banco, sua conexão deve ficar associada à sua sessão e cada nova operação no banco utiliza esta conexão proprietária.
Dependendo de sua implementação de connection pooling, é possível reaproveitar a conexão se ela já tiver sido feita com o mesmo usuário e senha de uma conexão que foi aberta e devolvida ao pool, e criar uma nova se tal conexão ainda não estiver no pool. Outros bancos de dados permitem que se reuse uma conexão com nova autenticação. Acho que não deve haver grandes problemas, mas é necessário checar sua implementação.
Atualmente estou utilizando o iBatis. Na implementação de referência que encontrei e reaproveitei é utilizado um bloco static {} para fazer a conexão com o banco.
Há a intenção de em breve migrar para o Hibernate ou JPA.
Você pode me passar referências sobre algum pool que faz o que você descreveu e se o Hibernate ou JPA resolvem este problema?
Só uma coisa se vc vai fazer desta forma não se esqueça de garantir a intergridade do banco; trate as SQL Ijection e Code Injection. Acho que a solução do nosso primeiro amigo é uma boa. Foi o que eu utilizei entretanto, não usei nenhuma camada de acesso ao banco.
Estou tentando fazer exatamente isso. Criar um pool de conexões e passar o usuário e senha a cada requisição de uma conexão ao pool.
Crio o pool assim: