Olá pessoal, tudo bom? A pedido de algumas pessoas, hoje vou falar como criar um sistema de login bem simples, porém dinâmico, ou seja, vamos fazer a validação sem a necessidade de recarregar a página, utilizando AJAX.
Confira o resultado final aqui (para acessar, utilize as informações que foram inseridas de exemplo)
1. Banco de dados
Inicialmente iremos criar nosso banco de dados:
CREATE TABLE `usuario` ( `usuario_id` INTEGER NOT NULL AUTO_INCREMENT, `login` VARCHAR(28) NOT NULL, `senha` varchar(80) NOT NULL, `nome` varchar(60) NOT NULL, PRIMARY KEY (`usuario_id`) ) ENGINE = MyISAM;
Bem simples, apenas contém uma chave primária (ID), o login, a senha e o nome do usuário. Vamos agora inserir alguns registros de exemplo:
INSERT INTO usuario VALUES (1, 'admin', 'admin', 'Administrador'); INSERT INTO usuario VALUES (2, 'rafael', 'couto', 'Rafael Couto Alves'); INSERT INTO usuario VALUES (3, 'foo', 'bar', 'Fulano');
2. Formulário de login (index.html)
Vamos criar a aparência da nossa página de login:
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 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Entrar</title> </head> <body> <form id="frmLogin" action="ajax/logar.php" method="post"> <fieldset> <legend>Entrar</legend> <div class="loader" style="display: none;"><img src="image/loader.gif" alt="Carregando" /></div> <div class="mensagem-erro"></div> <p> <label for="login">Usuário</label> <br /> <input type="text" id="login" name="login" /> </p> <p> <label for="senha">Senha</label> <br /> <input type="password" id="senha" name="senha" /> </p> <input type="submit" value="Entrar" /> </fieldset> </form> </body> </html> |
Nada de mais, é apenas um formulário HTML com dois campos, login e senha, e um botão de submit. No cabeçalho (head) de nossa página, vamos incluir uma biblioteca e um plugin javascript:
1 2 | <script type='text/javascript' src='js/jquery.js'></script> <script type='text/javascript' src='js/jquery.form.js'></script> |
- Linha 1: incluindo a biblioteca indispensável: jQuery.
- Linha 2: incluindo um plugin para jQuery, o jQuery Form. Ele facilita a requisição AJAX, pois não precisamos pegar e passar cada campo (como é feito nesse artigo, por exemplo), o plugin já faz este trabalho pela gente.
3. jQuery (index.html)
Nessa parte, vamos recuperar as informações do formulário e enviar para a página PHP. Adicione o seguinte código no cabeçalho de nossa index.html:
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 35 | // Quando carregado a página $(function($) { // Quando enviado o formulário $('#frmLogin').submit(function() { // Limpando mensagem de erro $('div.mensagem-erro').html(''); // Mostrando loader $('div.loader').show(); // Enviando informações do formulário via AJAX $(this).ajaxSubmit(function(resposta) { // Se não retornado nenhum erro if (!resposta) // Redirecionando para o painel window.location.href = 'painel.php'; else { // Escondendo loader $('div.loader').hide(); // Exibimos a mensagem de erro $('div.mensagem-erro').html(resposta); } }); // Retornando false para que o formulário não envie as informações da forma convencional return false; }); }); |
Vamos analisar o código:
- Linha 5: Aplicamos o evento submit no formulário (#frmLogin), ou seja, assim que o usuário clicar em entrar este método será chamado.
- Linha 14: Através do método ajaxSubmit() do nosso plugin, as informações do formulário são enviadas para seu action (logar.php), através do método definido no formulário, no caso, POST. Isso é o equivalente ao .post() nativo do jQuery, porém o plugin já captura e envia as informações para nós;
- Linha 17: Verificamos se a resposta retornada pelo nosso logar.php é falsa, ou seja, 0;
- Linha 19: Se a resposta for falsa, significa que o login deu certo, portanto redirecionamos o usuário para seu painel (painel.php);
- Linha 26: Se o login não deu certo, colocamos a mensagem retornada pelo logar.php na div cujo a classe é mensagem-erro;
- Linha 32: Precisamos retornar false para que o formulário não seja enviado, pois nós já enviamos as informações e recebemos a resposta via AJAX.
4. Conexão e configuração (config/conn.php)
Aqui vamos criar nosso arquivo para fazer a conexão com o banco de dados, nesse arquivo também vamos criar um método para carregar automaticamente a classe de login que veremos adiante.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?php // Informações para conexão $host = 'localhost'; $usuario = 'root'; $senha = 'senha'; $banco = 'banco'; // Realizando conexão e selecionando o banco de dados $conn = mysql_connect($host, $usuario, $senha) or die(mysql_error()); $db = mysql_select_db($banco, $conn) or die(mysql_error()); // Definindo o charset como utf8 para evitar problemas com acentuação $charset = mysql_set_charset('utf8'); // Função para carregar a classe automaticamente, quando instanciado um objeto function __autoload($class) { require_once(dirname(__FILE__) . "/../class/{$class}.class.php"); } ?> |
5. Logando (ajax/logar.php)
Este arquivo será responsável por fazer criar o login do usuário. Para facilitar e diminuir muitas linhas de código eu criei uma classe simples (a classe deste artigo foi melhorada, porém os métodos são os mesmos) para fazer a ações básicas de um login. Portanto, nosso código fica da seguinte maneira:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?php // Incluindo arquivo de conexão/configuração require_once('../config/conn.php'); // Instanciando novo objeto da classe Login $objLogin = new Login(); // Recuperando informações enviadas $login = $_POST['login']; $senha = $_POST['senha']; // Se conseguir encontrar o usuário e a senha estiver correta if ($objLogin->logar($login, $senha)) // Retornando falso, ou seja, esta tudo certo echo false; else // Retornando mensagem de erro echo 'Login ou senha inválidos'; ?> |
Repare que não foi necessário incluir o arquivo da classe Login, pois no arquivo de configuração (config/conn.php) foi definida a função __autoload(), ou seja, assim que o objeto $objLogin é criado, o __autoload() se encarrega de incluir o arquivo da classe, porém o arquivo da classe deve seguir o padrão: Classe.class.php.
Vamos a alguns detalhes:
- Linha 6: Criamos um objeto da nossa classe Login. Por padrão a tabela é usuario, a chave primária é usuario_id, o campo login é login e o campo senha é senha. Porém, poderíamos definir outras informações passando os parâmetros do construtor, exemplo:
$objLogin = new Login('tb_usuarios', 'codigo', 'campo_login', 'campo_senha');
- Linha 13: O método logar() aceita um terceiro parâmetro que é para onde o usuário será redirecionado se o login e senha estiverem corretos, no caso, isso não nos interessa, pois esta é uma página que será recebida pela requisição AJAX, portanto o método irá apenas retornar true, se as informações estiverem corretas, ou, caso contrário, false.
6. Painel do usuário (painel.php)
Esta é uma das página da qual apenas um usuário que esteja logado terá acesso, para isso, precisamos apenas verificar se o usuário está logado:
<?php // Incluindo arquivo de conexão/configuração require_once('config/conn.php'); // Instanciando novo objeto da classe Login $objLogin = new Login(); // Verificando se o usuário está logado, caso contrário será redirecionado para a página de login if (!$objLogin->verificar('index.html')) // Finalizado o script, apenas para garantir que o usuário não irá ver o conteúdo da página exit; ?>
Depois que reconhecido que o usuário está logado. podemos recuperar o ID e o login do usuário que estão na sessão, através do objeto de login, por exemplo:
<?php echo "ID: {$objLogin->getID()} <br />"; echo "Login: {$objLogin->getLogin()}"; ?>
Tendo o ID, podemos recuperar todas as suas informações, fazendo um simples SELECT:
1 2 3 | // Selecionando informações do usuário $query = mysql_query("SELECT * FROM usuario WHERE usuario_id = {$objLogin->getID()}"); $usuario = mysql_fetch_object($query); |
Sendo assim, podemos mostrar as informações que não estão na sessão:
echo "Bem vindo {$usuario->nome}";
7. Logout (sair.php)
Para finalizar a sessão é muito simples:
<?php // Incluindo arquivo de conexão/configuração require_once('config/conn.php'); // Instanciando novo objeto da classe Login $objLogin = new Login(); // Finaliza a sessão e redireciona o usuário para a página de login $objLogin->logout('index.html'); ?>
8. Finalizando
Bom pessoal, por hoje é isso, tentei detalhar o máximo possível, mas não houve tempo para explicar sobre a estrutura da classe, nem alguns detalhes sobre a programação orientada a objetos, isto fica para uma próxima, ok?
Espero que vocês tenham entendido e que a idéia seja útil para vocês.
Qualquer dúvida, sugestão ou critica construtiva, deixe um comentário ou envie um email.
Até a próxima, abraços.
Rafael, gostaria de parabeniza-lo não só por este post mas sim por todo seu blog.
Cheguei até seu site procurando um sistema (meio pronto) para login no google, e acabei achando este maravilhoso post.
Apos isto, percebi que em seu blog tem VARIAS coisas que serão MUITO UTEIS pra mim.
Muito obrigado e novamente meus parabens.
IDEM
Olá Rafael,
Pode me ajudar? está dando erro quando sou direcionado para a pagina painel.php
Warning: mysql_fetch_object(): supplied argument is not a valid MySQL result resource in C:\xampp\htdocs\upload\login\painel.php on line 15
// Selecionando informações do usuário
$query = mysql_query(“SELECT * FROM usuario WHERE usuario_id = {$objLogin->getID()}”);
$usuario = mysql_fetch_object($query);
Olá Ricardo,
Provavelmente há alguma problema na sua SELECT, você utilizou a mesma estrutura de banco do artigo? Tente rodar o comando SQL no phpMyAdmin (por exemplo) e veja se está funcionando, ou tente assim:
Desse modo ele vai mostrar a mensagem de erro, e então descobrimos o problema.
Abraço.
Parabéns pelo ótimo tutorial, era o que eu estáva precisando foi mesmo de grande ajuda! Só uma dúvida: Como faço para colocar um nivel de acesso para cada página? criei um campo no banco onde pode-se ter o nível 1 e 2 não consigo implementar isso no Login.class. Se puder me ajudar ficarei eternamente grato.
Parabéns pelo tutorial….gostei muito…
Muito obrigado pelo post! Que Deus lhe abençoe ricamente em nome do Senhor Jesus amém!
Cara, quando eu tenho mais de um usuário cadastrado no banco e atualizo a página o usuário muda. Parece q a SESSION não grava. Pode me ajudar? Tô usando a tua class.
kra mt bom o blog, todos os posts, tava procurando um sistema desses msm, vlw ajudou bastante.
Parabens pelo tutorial, era o que estava precisando, ha muito tempo estava procurando um codigo completo como este que pudesse me ajudar a implementar no meu projeto.
So uma dúvida exite alguma outra maneira de fazer a consulta no banco sem criar a classe login?
No meu projeto nao estou usando POO.
Abraço
Olá Max,
Obrigado.
Não tem importância, você pode incluir (include) a classe no seu arquivo .php e usar os métodos dela, independente se seu projeto é POO ou estruturado.
Abraço.
Estou com um problema… Quando acesso a página do sistema que é protegida com Login, em duas abas no Browser e ao clicar em sair do sistema em uma das abas… E em seguida ao acessar a Aba que continua com o sistema aberto… (Para utilizar alguma de suas aplicações) A página de Login é carregada em uma Div dentro da própria pagina *Protegida… :/ O correto é a pagina Atual ser substituída pela página de login.php e não o mesmo ser carregado dentro da pagina Protegida..
Para redirecionar estou utilizando: header(‘Location: login.php’);
Como posso resolver esse problema?
Obrigado pelas Dicas…
Complementando:
Estou enviando as variáveis pelo Jquery.post() e ao chegar no validar.php ele não troca de página, na verdade ele retorna a página de login.php na Div retorno… OK
Obg pela dica Rafael.
Você não tem ideia de como me ajudou! rsrsrs
Abraço.
Vlw Parceiro.
Rafael gostaria de entender melhor a variavel $redireciona na classe.Login , entendi que ela é uma boolean porém nao entendi o funcionamento exatamente.
Por exemplo:
function logar($login, $senha, $redireciona = null) ela ja recebe null
e dai por diante é feita a consulta no banco, se encontra usuario é instaciado e registramos a sessão logo após….
if ($redireciona !== null)
header(“Location: {$redireciona}”); qual o valor de $redireciona aqui neste momento ? para onde o location vai enviar o usuario?
else
return true;
ela se repete mais na frente em outros metodos, mas pelo que vi minha duvida é como ela funciona e qual o valor guardado nela que direciona para outro caminho?
Mais uma vez agradeço desde já a atenção
Abraço
Max.
Muito bom esse post! Meus parabéns! Mas quanto a segurança, não tem problema salvar o usuário na sessão?
parabéns pela postagem. Obrigado por compartilhar.