Canais iMasters

MySQL + PHP

Autenticação de usuários em PHP usando sessões e MySQL

Esse artigo é um passo-a-passo da criação de um sistema de autenticação de usuários usando banco de dados MySQL e, principalmente, as poderosas sessões do PHP. Mostro também como trabalhar com senhas em MD5 e permissões para os usuários.

Através desse artigo, espero que você consiga tirar todas suas dúvidas sobre como deve ser desenvolvido um sistema de autenticação. Esse artigo mostra a principal base, o qual você poderá facilmente adaptar às suas necessidades.

As senhas serão criptografadas em hash MD5, aumentando o nível de segurança.

Vou usar como exemplo um sistema de notícias, onde as notícias serão visíveis apenas para usuários registrados. Usuários registrados também poderão enviar novas notícias.

Tópicos:

01. Tabelas no MySQL

Primeiramente vamos criar as tabelas no MySQL do nosso sistema de notícias. As tabelas se chamarão aut_noticias e aut_usuarios, referentes às Notícias e Usuários respectivamente.

Código SQL das tabelas:

O campo postar da tabela aut_usuarios registra a permissão do usuário, se ele poderá postar (valor S) ou não (valor N) novas notícias.

Agora, vamos inserir alguns dados na tabela, para que o exemplo do artigo funcione. Aqui irei dar tudo pronto, mas no seu caso, em seu sistema, você deverá criar uma seção para adicionar usuários, notícias, etc... Mas isso fica fora do escopo desse artigo.

Usuários:

Notícias:

Perceba as senhas criptogradas em MD5. Para isso, use a função md5("senha_aqui") e então salve o valor gerado no banco de dados, no caso, as senhas são senha123 e teste respectivamente. Eu usei o código abaixo para saber o MD5 para salvar no banco de dados:

<?php
echo md5("senha123");
echo
"<br>";
echo
md5("teste");
?>

Veja também que a hora na tabela de notícias está apenas em um valor numérico. Para isso, usei a função time() do PHP. Para você saber qual é essa data e hora, use a função date(). Isso será mostrado adiante.

02. Conexão com o banco de dados

Vamos agora criar o arquivo comum.php onde existirá a conexão de banco de dados, usado em todas as páginas.

<?php
// Conecta-se com o MySQL
mysql_connect("localhost", "root", "root");

// Seleciona banco de dados
mysql_select_db("noticias");
?>

03. Criando o formulário e script de Login

Página com o formulário onde o usuário digitará o login e senha:

Agora vamos criar a página login_vai.php, o qual recebe os dados do formulário login.html e efetua o login do usuário.

<?php
// Conexão com o banco de dados
require "comum.php";

// Inicia sessões
session_start();

// Recupera o login
$login = isset($_POST["login"]) ? addslashes(trim($_POST["login"])) : FALSE;
// Recupera a senha, a criptografando em MD5
$senha = isset($_POST["senha"]) ? md5(trim($_POST["senha"])) : FALSE;

// Usuário não forneceu a senha ou o login
if(!$login || !$senha)
{
    echo
"Você deve digitar sua senha e login!";
    exit;
}

/**
* Executa a consulta no banco de dados.
* Caso o número de linhas retornadas seja 1 o login é válido,
* caso 0, inválido.
*/
$SQL = "SELECT id, nome, login, senha, postar
        FROM aut_usuarios
        WHERE login = ""
. $login . """;
$result_id = @mysql_query($SQL) or die("Erro no banco de dados!");
$total = @mysql_num_rows($result_id);

// Caso o usuário tenha digitado um login válido o número de linhas será 1..
if($total)
{
    
// Obtém os dados do usuário, para poder verificar a senha e passar os demais dados para a sessão
    
$dados = @mysql_fetch_array($result_id);

    
// Agora verifica a senha
    
if(!strcmp($senha, $dados["senha"]))
    {
        
// TUDO OK! Agora, passa os dados para a sessão e redireciona o usuário
        
$_SESSION["id_usuario"]   = $dados["id"];
        
$_SESSION["nome_usuario"] = stripslashes($dados["nome"]);
        
$_SESSION["permissao"]    = $dados["postar"];
        
header("Location: index.php");
        exit;
    }
    
// Senha inválida
    
else
    {
        echo
"Senha inválida!";
        exit;
    }
}
// Login inválido
else
{
    echo
"O login fornecido por você é inexistente!";
    exit;
}
?>

Veja o uso da função strcmp na comparação das senhas. Ela está comparando as duas senhas já criptografadas em hash MD5. Lembrando que a função strcmp retorna ZERO caso 2 strings sejam iguais, por isso o uso do operador NOT (!) na frente da mesma.

04. Verificando se usuário está logado no sistema

Agora, o script verifica.php que verifica a sessão do usuário se ele está logado ou não. Caso não esteja logado, o redireciona para a página de login.

<?php
// Inicia sessões
session_start();

// Verifica se existe os dados da sessão de login
if(!isset($_SESSION["id_usuario"]) || !isset($_SESSION["nome_usuario"]))
{
    
// Usuário não logado! Redireciona para a página de login
    
header("Location: login.html");
    exit;
}
?>

Em todo script que você usar sessões, é obrigatório que você inicie as mesmas, chamando a função session_start() no começo dos scripts.

Para as páginas que você quiser deixar como restritas, simplesmente inclua o arquivo verifica.php.

05. O script de notícias

Enfim! Chegamos ao principal desse artigo! O script de notícias, onde tudo o que foi criado acima será usado. Esse arquivo é o index.php.

<?php
// Verificador de sessão
require "verifica.php";

// Conexão com o banco de dados
require "comum.php";

// Imprime mensagem de boas vindas
echo "Bem-Vindo" . $_SESSION["nome_usuario"] . "!<BR>\n";

// Verifica e imprime quantidade de notícias no nome do usuário
$SQL = "SELECT id
        FROM aut_noticias
        WHERE autor_id = "
. $_SESSION["id_usuario"];
$result_id = mysql_query($SQL) or die(mysql_error());
$total = mysql_num_rows($result_id);

if(
$total)
{
    echo
"Há um total de " . $total . " notícia(s) de sua autoria!\n";
}
else
{
    echo
"Não há nenhuma notícia de sua autoria!\n";
}

/**
* Verifica se usuário tem permissão para postar novas notícias.
* Caso positivo, imprime link para postagem de notícias
*/
if($_SESSION["permissao"] == "S")
{
    echo
" | <a href="nova.php">Postar nova notícia</a>\n";
}

// Imprime link de logout
echo " | <a href="sair.php">Sair do Sistema</a>";

echo
"<br><br>\n";

/**
* Imprime as notícias
*/
$SQL = "SELECT id, titulo, data
        FROM aut_noticias
        ORDER BY data DESC"
;
$result_id = mysql_query($SQL) or die(mysql_error());
$total = mysql_num_rows($result_id);

if(
$total)
{
    
// Abre tabela HTML
    
echo "<table border=1 cellpadding=3 cellspacing=0>\n";
    echo
"<tr><th>Id</th><th>Título</th><th>Data</th></tr>\n";

    
// Efetua o loop no banco de dados
    
while($dados = mysql_fetch_array($result_id))
    {
        echo
"<tr><td>" . $dados["id"] . "</td><td><a href="ver_noticia.php?id=" . $dados["id"] . "\">" . stripslashes($dados["titulo"]) . "</a></td>";
        echo
"<td>" . date("d/m/Y à\s H:i:s", $dados["data"]) . "</td></tr>\n";
    }

    
// Fecha tabela
    
echo "</table>\n";
}
else
{
    echo
"<B>Nenhuma notícia cadastrada!</B>\n";
}
?>

O script de notícias verifica se usuário tem permissão para postar novas notícias. Caso sim, imprime o link para a postagem. O arquivo para postar notícias não será explicado aqui, pois fica fora do escopo desse artigo, mas, um exemplo de como deve ser feito:

<?php
// Verificador de sessão
require "verifica.php";

// Verifica se usuário tem permissão para postar notícia
if($_SESSION["permissao"] !== "S")
{
    echo
"Você não tem permissão para postar notícias!";
    exit;
}

// Se o script continuar aqui, é que o usuário tem permissão
// Então.. seu formulário de postagem abaixo
?>

É sempre recomendável que você coloque um link para que o usuário encerre a sessão de login atual (sessões são encerradas com a função session_destroy()), caso ele não queira mais permanecer na página. No nosso exemplo, a página é a sair.php:

<?php
// Inicia sessões, para assim poder destruí-las
session_start();
session_destroy();

header("Location: login.html");
?>

06. Sistema em funcionamento

Agora é hora de testar tudo! Primeiro, logue-se com o login "einstein" e senha "senha123". Esse usuário tem permissão para postar novas notícias e tem 2 notícias postadas.

Clique em "Sair do Sistema" e logue-se com o login "admin" e senha "teste". O usuário não tem permissão para escrita e tem apenas uma notícia postada (por exemplo, como ele não tem permissão para escrita, então deve ter sido um administrador postado a notícia com o nome desse usuário).

Obs: caso a versão do seu PHP seja anterior à 4.1.0, use a variável $HTTP_SESSION_VARS no lugar da superglobal $_SESSION.

Clique aqui para fazer o download dos códigos desse artigo.

E é isso! Até o próximo!

Alfred Reinold Baudisch

Alfred Reinold Baudisch

é desenvolvedor PHP e administrador de projetos web há mais de 3 anos. Adepto totalmente à OOP usando os melhores padrões de programação.


Comente também

27 Comentários

Plínio Monteiro Brandão
Plínio Monteiro Brandão

Muito ótima essa matéria. Aprendi a fazer algo que não sabia que era gerar o link nos resultado das consultas. Agora o arquivo ver_noticia.php não veio junto, mas pelo menos já fica mais fácil. )

Bom começo. :)

Snape
Snape

Já fiz vários scripts usando sessions mas nuca funciona. Baixei vários exemplos e tambem não funcionou. Ocorre o seguinte erro:
Nao foi possivel Inicializar a Sessao, logo abaixo aparece outro erro, dizendo: pasta não encontrada (/tmp), sessao já criada.
Gostaria que me ajudassem, certo da atenção, Obrigado!!!

Edizania
Edizania

Weudes : se você utiliza windows, vai no arquivo de configuração do php e prucura por /tmp e troque por "c:\tmp" e também crie uma pasta na raiz (C:\) com o nome tmp.

[]'s

jura
jura

Eu já havia visto este artigo em outros sites. Realmente é um artigo muito bom. Eu acho que ficaria melhor ainda se tivesse a área de noticias. O autor bem que poderia acrescentar isso. Para que fosse possível ver o sistema funcionando por completo.

Ricardo
Ricardo

Este é um grande problema, já que a grande maioria de internautas não efetua logoff, e sim vão direto no botão para fechar a janela do navegador.

Como podemos resolver isso e impedir que o sistema mantenha o usuário logado após fechar a janela do navegado?
Obrigado!

Fernando Lima
Fernando Lima

Minha pergunta é a mesma do Ricardo:
(Publicado por Ricardo, 24/11/2004 às 14:08 )
Este é um grande problema, já que a grande maioria de internautas não efetua logoff, e sim vão direto no botão para fechar a janela do navegador. Como podemos resolver isso e impedir que o sistema mantenha o usuário logado após fechar a janela do navegado? Obrigado!

Leandro
Leandro

Fiz tudo legal, mas quando logo, aparece a página login_vai.php totalmente em branco. Aliás, já é o terceiro código fonte que uso de login e o problema é parecido. Sempre depois do login ou a página não é aberta (continua na mesma) ou aparece totalmente em branco. Por favor alguém me ajude ! Obrigado!

Alexandre  Pereira dos Santos
Alexandre Pereira dos Santos

O meu problema é o mesmo do ultimo comentario quando logo, aparece a página login_vai.php totalmente em branco. Preciso de ajuda pois ainda estou aprendendo a Obrigado!

José Tito do Canto Neto
José Tito do Canto Neto

ola...muito bom o artigo funciono muito bem...mas tenho uma duvida se vc puder responder...

Como proceder para mostrar somente as noticias do usuario logado??...e não todas...!!

e o q fazer para os links levarem ate as noticias?


obrigado

Marcos
Marcos

O PHP 5 tem problemas com as sessions?

mankuzzo .
mankuzzo .

... O meu prob. é o mesmo de algumas pessoas que já postaram nessa matéria, a pág. login_vai.php está voltando em branco o que fazer pra corrigir isso se for um erro é claro ... desde já agradeço ...

Alfred Reinold Baudisch
Alfred Reinold Baudisch

Primeiramente, obrigado a todos pelos comentários. Quanto ao login_vai.php ela não contém nenhum erro nem o PHP dos senhores. Verifiquem se arquivos incluídos não possuem espaço em branco antes do <?php e depois do ?>. Eu verifiquei todos os arquivos aqui, já que essa matéria é meio antiga, e realmente está funcional em PHP 4 e PHP 5.

Alfred Reinold Baudisch
Alfred Reinold Baudisch

O intuito da matéria é mostrar de modo bem básico e enxuto a lógica por trás de uma autenticação. Ou seja, como organizar essa estrutura (mas, como falei, é MUITO básica, somente para ter idéia inicial - NÃO SERVE PARA UM SISTEMA PROFISSIONAL essa lógica de autenticação que aqui passei). Já um sistema de notícias seria fora do foco do artigo. Aqui no iMaster mesmo tem algo relacionado ;).

Joeber Gonçalves Garcia
Joeber Gonçalves Garcia

Apesar do método ser um método bem básico de autenticação, como o próprio autor citou, venho dizer para os usuários mais inexperientes tomarem cuidado com a sessões usando apenas a verificação com a função 'isset'. Pois vc vai estar verificando se a variável de sessão existe, ou seja, se ela existe, qualquer sistema que tiver o mesmo nome da variável de sessão poderá acessar o sistema. Exemplificando, tomamos como exemplo um site com uma página onde há restrições usando este sistema de autenticação neste endereço, www.dominio.com.br/clientesA.php, o usuário vai acessar esta página se a variável de sessão 'LOGADO', por exemplo, existir, ou seja, if(isset($logado)), dessa forma, se um outro site, que usa PHP também tiver uma instrução idêntica numa página por exemplo www.dominioB.com.br/outroCliente.php ele poderá acessar o sistema apenas digitando o endereço na mesma janela do browswer, (obs: não estou dizendo abrir uma nova janela, e sim, na mesma janela) o sistema estará acessível também na página PHP, por que o teste (if(isset($logado)) vai dar como verdadeiro também em ambos os endereços.

Joeber Gonçalves Garcia
Joeber Gonçalves Garcia

O problema em usar este método é que, ao registrar uma variável de sessão, de nome, por exemplo, "nome_usuario", qualquer programador, poderá hospedar um script em algum servidor, ele poderá supor que o programador usou o nome 'nome_usuario' para registrar sua variável de sessão, e criar uma página simples onde ele dá qualquer valor para esse variável de sessão, e executar esta página no seu servidor e depois pela mesma janela do browser digitar o endereço do sistema que quer entrar bastando digitar o url do sistema. Dessa forma ele conseguirá acessar o sistema sem ter que digitar seu nome de usuário e senha por que no sistema é feito apenas o teste se a variável 'nome_usuario' existe.

Claro, que isso só é possível se o programador adivinhar o nome da variável de sessão.

Uma forma de contornar esse problema, é criar uma tabela exclusiva para uma 'senha de segurança' do seu sistema e também ao registrar as variáveis de sessão, registre uma outra variável de sessão para guardar essa senha de segurança só que com seu valor digitado manualmente para que este valor seja testado depois com a mesma senha de segurança que vc guardará na tabela da senha de segurança.

No script verifica.php, além de vc fazer o teste se as variáveis de sessão 'id_usuario' e 'nome_usuario' existem, vc também, faria o teste se a variável de sessão da senha de segurança é a mesma da tabela da senha de segurança.

Abraços...

Julian Silva
Julian Silva

Seguinte, passei já algumas horas fazendo teste e por fim descobri que ocorre erro sempre que ouver o session_start e coisas em html. Assim sendo se você mandar dar um include no verifica.php em alguma pagina que tenha html ele não funciona.

Joeber Gonçalves Garcia
Joeber Gonçalves Garcia

Prezado amigo Julian Silva, não sei se é isso mesmo que vc está fazendo mas vc não pode colocar nenhum tipo de código antes do session_start(), a função session_start() tem que ser o primeiro de tudo em uma página. Não pode haver nada antes dele. Verifique se é isso que vc está tendo problemas!

Ramon Leonardi
Ramon Leonardi

Em login_vai.php, acredito que o teste abaixo não funciona como esperado:

// Usuário não forneceu a senha ou o login
if(!$login || !$senha)
{
echo "Você deve digitar sua senha e login!";
exit;
}

Dado que a função md5() criptografa mesmo um strings vazios.
Teste por exemplo:
<?php
print md5("");
?>
resultado:
d41d8cd98f00b204e9800998ecf8427e

Isto significa que $senha sempre existirá. Ou seja, o teste só funciona se o usuário não fornece login.

Mario Moreira
Mario Moreira

A apostila e muito boa..............

Silvia Regina
Silvia Regina

Tenho uma dúvida, eu estou criando um sistema no qual cada usuário é uma empresa diferente e tem o seu proprio banco de dados que será hospedado num único servidor. Eu queria saber como é que eu faço para que o banco de dados seja selecionado dinamicamente, ou seja, o banco será selecionado de acordo com o nome da empresa que o usuario digitar.
Sou iniciante em PHP, se puder me ajudar...
Abraços e parabéns pelo tutorial

Rander Carlos
Rander Carlos

Aê pessoal,

adicionei as funções de postar uma nova notícia e de visualizar os detalhes da notícia a esse sistema de notícias. Está bem simples, mas com certeza está muito bom. Para vê-lo em funcionamento basta ir no arquivo "conexao.php" e alterar os parâmetros das funções mysql_connect e mysql_select_db. Depois basta rodar o "noticias.sql" no banco de dados. Espero que gostem

http://rapidshare.com/files/340484512/sistema_login_noticias.rar.html.

Erick Basilio
Erick Basilio

Parabéns pelo tutorial. É simples, completo e útil. Tentei fazer o download pelo link acima (http://rapidshare.com/files/340484512/sistema_login_noticias.rar.html) mas o link está quebrado, teria como disponibilizá-lo? Obrigado.

Cezar Gonçalves
Cezar Gonçalves

Ai gente, tipo que quando iniciei a propgramar em PHP tive muitos problemas
com erros principalmente quando se usa a função start_session, ou então, header()
sempre me retornava erro, até que pesquisei mto até descobrir que maioria dos erros
são por causa da formatação de caracteres do editor, que no meu caso era o Dreamwaver
continuo usando ele só que quando surge algum erro , apenas abro o código php no bloco
de notas e salvo novamente como formatação de caracteres "ASCII" só assim pudi corrigir os problemas,
há e ressaltando que carácteres com acento e "ç" são perdidos =/
Espero ter ajudado , abraços =)

Henrique
Henrique

Está dando uma série de erros em login_vai.php. Um ex:

Parse error: syntax error, unexpected '"', expecting T_STRING or T_VARIABLE or T_NUM_STRING in C:\xampp\htdocs\login_vai.php on line 53

Felipe Alfaville
Felipe Alfaville

Adorei vei!!
Ta de parabens!!!

Joel
Joel

Estou criando um site, mas não estou conseguindo fazer o login usando md5. Consigo fazer o cadastro, o banco de dados recebe a senha encriptada, mas na hora de fazer o login não consigo acessar a area restrita. Pode ajudar.

Antonio
Antonio

Ao Joel: tive o mesmo problema. Talvez a solução seja esta:

id1: login: einstein; senha: senha123
id2: login: admin; senha: teste

Qual a sua opinião?

Comentários considerados ofensivos serão moderados.

Parceiros

IBM
PagSeguro
Internet Innovation
Dialhost
HostNet
Tecla
KingHost
DotStore
Dinamize