Como controlar a autenticação de usuários e o acesso ao BD

Olá pessoal,

Tenho diversos DAOs, sendo que a conexão ao BD é criada dentro de cada um deles através de um ConnectionFactory que criei. O ConnectionFactory tem um método estático getConnection que recebe o nome do usuário no banco e a respectiva senha, realiza a conexào e retorna a dita cuja para o DAO solicitante.

Como fazer para que, a cada vez que eu instanciar um DAO, não precisar ficar passando o login e senha do usuário para autenticação?!

Ah, é uma aplicação WEB.

Obrigado!

Se vc criasse um método ConnectionFactory que retornasse uma Connectio através de getConnection:

public class ConnectionFactory 
{

	public static Connection getConnection()
	{
		try 
		{
			Class.forName("com.mysql.jdbc.Driver");
			System.out.println("Conectando com o banco");
		} 
		catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		Connection con = null;
		try 
		{
			con = DriverManager.getConnection("jdbc:mysql://localhost/banco","user","senha");
		} catch (SQLException e) 
		{
			e.printStackTrace();
		}
		return con;
	}
}

e dentro do construtor da sua DAO vc abrisse a conexao:

public class ContatoDAO 
{
	private Connection connection;
	
	public ContatoDAO()
	{
		this.connection = ConnectionFactory.getConnection();
	}
       //etc
}

Não resolveria seu problema???

Mas assim qualquer usuário iria se conectar com o mesmo login e senha padrão? Eu queria amarrar o nome/senha de cada usuário com o que eles já tem cadastrado no BD, pois esse BD já é utilizado em outra aplicação desktop, que realiza autenticação direto no banco, mas é escrita em C++ e não utiliza pattern nenhum, é tudo misturado, regra de negócio, sql, etc…

Cassio,

coloca seu código aí pra gente ter uma idéia do que voce realmente quer.

Fiz essa ConnectionFactory:

package br.com.cshagn;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;

import java.util.Properties;

public class ConnectionFactory {
	
	public static Connection getConnection(String user, String password) throws SQLException{
		Connection conn = null;
		try{
			File file = new File("/resources/cshagn.properties");
			Properties props = new Properties();
			FileInputStream fis = new FileInputStream(file);
			props.load(fis);
			Class.forName(props.getProperty("driverName"));
			conn = DriverManager.getConnection(props.getProperty("cshagn.connectionPath")+
					                           props.getProperty("cshagn.dbServerPort")+
					                           "//"+ props.getProperty("cshagn.dbServerHost")+
					                           "/"+ props.getProperty("cshagn.dbName"),
					                           user, password);			
		}
		catch(ClassNotFoundException cnfe){
			throw new SQLException(cnfe.getMessage());
		}
		catch(IOException ioe){
			System.out.println("Arquivo cshagn.properties nao encontrado." + ioe.getMessage());
		}
		finally{
			conn.close();
		}
		return null;
	}
}

Como pode ver, o método getConnection recebe o nome de usuário e a senha. Imaginei fazer de um jeito que esses dados fossem os mesmos que o usuário utilizou para se logar no sistema, pois estes usuários e senhas já estão cadastrados no banco de dados que vou utilizar. Todos os DAOs pegarão a conexão através dessa Factory. Porém, dessa forma eu teria que estar sempre passando o nome de usuário e a senha no contrutor de todos os DAOs… Isso seria muito ruim…

Queria uma maneira de mapear as conexões com os usuários logados, minimizando essa repetição de código que o modelo acima provocaria. Na verdade preciso ter uma conexão autenticada com nome de usuário e senha diferentes para cada usuário do sistema, por isso não posso adotar a solução que vc colocou acima…

Sugestão: crie uma lista mapeando cada usuário logado (session???) com uma connection. No login do sistema você abre a conexão e insere nesta lista. No ConnectionFactory.getConnection você percorre a lista e devolve a connection deste usuário. No logout, retire da lista e feche a conexão. Vai ser necessário criar um mecanismo de “inatividade” da conexão, pois senão pode correr o risco de ficar muitas conexões abertas que o usuário “foi embora”.

Tome cuidado se vai ser possível abrir outra janela e logar de novo (mesma session).

Estou com o mesmo problema, mas ainda não resolvi. Se lhe ajudar postei aqui no fórum um questionamento semelhante: http://www.guj.com.br/posts/list/47042.java

Sugestão:

Ao invés de criar a conexão dentro do DAO, crie na classe de negócio, ou de controle.

Como é um sistema WEB, vc pode criá-la no login do usuário, guardar em uma ThreadLocal amarrada a sessão do usuário, e os seus DAO’s, ao invé de criar a Connection, receberia ela no construtor do DAO.

Assim vc cria a connection no login e reutiliza o resto da vida util da sessão.

Acho que uma solução bastante razoável é a descrita pelo thingol no post mencionado acima, ou seja, o pool de conexões se encarrega de autenticar o usuário no banco se ele ainda não o fez. Se ele já foi autenticado, a conexão é obtida através do pool.

Só objetos que podem ser serializados devem ser adicionados a uma sessão.
Acredito que a solução com ThreadLocal não atende a este princípio.

[]'s

Daniel Augusto

Não me referia a colocar a ThreadLocal na Sessão, e sim amarrar a conection à sessão, através de uma Hash, onde a chave seria o id da sessão.

Seria semelhante a idéia do pool.

Concordo com você, por isso acho razoável a idéia fornecida pelo Thingol. Como estou com o mesmo problema, mas ainda não o resolvi (outras prioridades apareceram), aparentemente não precisaria ser feito nada. Esse trabalho seria feito pelo pool.

Portanto não precisaria ser criado este hash com o id da sessão, pois para o pool a chave será o usuário/senha da conexão.

Gostei das idéias que li aqui… tenho que fazer alguns testes para ver o que fica melhor implementar, mesmo porque ainda estou começando no desenvolvimento web.

Conforme forem surgindo dúvidas e idéias eu vou postando. Muito obrigado a todas as respostas!

E se você usar Spring + algum pool de conexões e deixar ele gerenciar isso?

hum… até eu aprender Spring… minha idéia seria utilizar algum framework mais simples e essa parte das conexões fazer na mão mesmo… mas vou acabar usando um pool mesmo…

Obrigado!

Ainda não utilizei o spring, mas fiquei curioso para ver como o DAO funcionaria com ele!

Você poderia me dizer onde eu posso ver um DAO de exemplo utilizando esse esquema? Ou se for muito simples vc poderia postar algo aqui pra gente ver?

Valews