Autenticar usuário e salvar uma cookie com PHP

Sistema de autenticação de usuários em PHP, onde se oferece a opção de memorizar seu usuário no computador e salvar uma cookie para lembrar o usuário e não ter que voltar a se autenticar.

Por Miguel Angel Alvarez - Tradução de JML


Publicado em: 17/3/08
Valorize este artigo:
Vamos criar um sistema para autenticar usuários com PHP, com a particularidade que este sistema vai a oferecer ao visitante a opção de salvar seu usuário, para que a página o lembre em sucessivos acessos e não tenha que voltar a se autenticar. O usuário será salvo em uma cookie para que o navegador possa lembrá-lo em suas distintas visitas.

Esta é uma opção muito útil para que o visitante não tenha que estar todo o tempo se autenticando, com seu usuário e senha, cada vez que acessa à página web. Certamente é uma opção que devemos ter visto em um montão de web sites.

Este artigo é uma continuação de uma série de workshops e exemplos que vimos anteriormente no manual de Autenticação de usuários em PHP. Neste workshop não vamos realizar uma autenticação muito elaborada, e sim uma bem simples, para facilitar o desenvolvimento. Logo, a complexidade aportará a parte de salvar o usuário em uma cookie, que não é difícil de fazer, porém sim requer de novos conhecimentos que aplicar.

Explicação de armazenar o usuário em uma cookie

Primeiro, vamos explicar com palavras o modelo de trabalho que vamos aplicar para armazenar o usuário em uma cookie. Não investiguei como poderão fazer isto outras pessoas em outros desenvolvimentos, porém acho que criei uma forma adequada para fazê-lo.

Digo isto porque o primeiro que pensei, foi colocar o nome de usuário e a senha em umas cookies. Seria simplesmente criar um par de cookies no sistema do usuário com essas duas variáveis. Porém, logo pensando, não me parecia muito atraente a possibilidade de incluir essa informação sensível em umas cookies no computador do usuário, pelo caso de haver alguma pessoa que pudesse lê-las, copiá-las e utilizá-las em outro computador. Talvez não deveria me preocupar com isso, porém de qualquer forma, não gostava da possibilidade de armazenar o nome de usuário e senha, e sim de armazenar outro tipo de informação menos crítica.

Então, o que pensei foi de armazenar o identificador do usuário. Mas claro, se alguém conseguia criar uma cookie no sistema com qualquer identificador de usuário, poderia acessar a conta desse usuário. Portanto, tinha que aplicar outra estratégia adicional para assegurar que esse identificador de usuário não se possa reproduzir. Finalmente, decidi gerar um número aleatório quando o usuário se conecta à página e se autentica corretamente, e armazená-lo em dois sites, primeiro no registro do usuário no banco de dados e logo, na cookie.

Sendo assim, quando o visitante decide que quer que o web site lembre sua conta de usuário, para não ter que voltar a se autenticar em seguintes acessos, se salvam duas coisas nas cookies do navegador: seu identificador de usuário e uma marca aleatória (tal marca também se armazena no banco de dados, associada ao seu usuário). Nos seguintes acessos, primeiro se comprova se existem essas cookies no navegador do visitante e se o conjunto de identificador de usuário e a marca aleatória armazenados na cookie coincidem com o que temos no banco de dados.

Com outras palavras, salvaremos na cookie o identificador de usuário. Ademais, geramos um número aleatório que salvamos em dois lugares: 1) na tabela de usuário, no registro correspondente ao usuário que deseja que se lembre a chave e 2) em uma cookie. Logo, quando os usuários se conectam de novo, não só se comprova que tenha a cookie com o identificador de usuário, como também que tenha a outra cookie com a marca aleatória e que seja a mesma que temos no banco de dados para esse mesmo usuário.

Espero que se possa entender o sistema. Não obstante, espero clareá-lo ainda mais à medida que explique o código PHP e o banco de dados que vamos utilizar.

Tabela de usuário

Na tabela de usuário que criamos para este exemplo temos 4 campos:
  • Identificador de usuário
  • Nome de usuário
  • Chave de acesso
  • Marca aleatória que se colocou na cookie
Para o exemplo, criamos uma tabela e inserimos dois usuários para fazer provas. Terá uma forma como esta:


Código da página PHP

Agora vou explicar por partes o código PHP para autenticar ao usuário e salvar a informação de acesso na cookie, assim como a parte de comprovar se o usuário tinha a cookie com seu acesso salvo no computador.

Primeiro, vamos começar mostrando o formulário HTML:

<form action="prova-cookies.php" method="post">
Usuario: <input type="text" name="usuario">
<br>
Chave: <input type="text" name="chave">
<br>
<input type="checkbox" name="salvar_chave" value="1"> Memorizar o usuário neste computador
<br>
<input type="submit" value="Entrar">
</form>


Como vemos, tem os campos para escrever o nome de usuário e a chave e um campo checkbox adicional para que o usuário marque se quer que seu acesso se salve em seu computador.

Agora vou mostrar o código que utilizaríamos para receber por post, do formulário de autenticação, o nome de usuário e senha. Este código também tem que detectar se o usuário queria que se salvasse seu acesso no computador.

//deveria comprovar se o usuario eh correto
$ssql = "select * from usuario where usuario = '" . $_POST["usuario"] . "' and chave='" . $_POST["chave"] . "'";
//echo $ssql;
$rs = mysql_query($ssql);
if (mysql_num_rows($rs)==1){
   //TODO CORRETO!! Detectei um usuario
   $usuario_encontrado = mysql_fetch_object($rs);
   //agora devo ver se o usuario queria memorizar sua conta neste computador
   if ($_POST["salvar_senha"]=="1"){
      //pediu para memorizar o usuario
      //1) crio uma marca aleatoria no registro deste usuario
      //alimentamos o gerador de aleatorios
      mt_srand (time());
      //geramos um número aleatorio
      $numero_aleatorio = mt_rand(1000000,999999999);
      //2) coloca a marca aleatoria na tabela de usuario
      $ssql = "update usuario set cookie='$numero_aleatorio' where id_usuario=" . $usuario_encontrado->id_usuario;
      mysql_query($ssql);
      //3) agora coloco uma cookie no computador do usuario com o identificador do usuario e a cookie aleatoria
      setcookie("id_usuario_dw", $usuario_encontrado->id_usuario , time()+(60*60*24*365));
      setcookie("marca_aleatoria_usuario_dw", $numero_aleatorio, time()+(60*60*24*365));
   }
   echo "Autenticado corretamente";
   //header ("Location: conteudos_protegidos_cookie.php");
   
}else{
   echo "Falha de autenticação!";
   echo "<p><a href='prova-cookies.php'>Voltar</a>";
}


Para comprovar se os dados de autenticação que recebemos pelo formulário são corretos, fazemos uma sentença SQL. Executamos e se der como resultado que temos um registro encontrado na tabela de usuários, é que o nome de usuário e chave correspondem com o de algum usuário.

Logo com a linha

if ($_POST["salvar_chave"]=="1"){

Comprovamos se o visitante tinha pedido que se armazenasse a chave em seu computador. Então, há que gerar as cookies correspondentes, que havíamos comentado anteriormente neste artigo.

Faremos em três passos:

  • Gero um número aleatório para que nos sirva de marca.
  • Insiro a marca aleatória na tabela de usuários, fazendo um update no registro do usuário autenticado que havíamos detectado anteriormente.
  • Gero e coloco no computador do usuário as duas cookies para salvar seu acesso no navegador: o identificador do usuário e a marca aleatória. Criamos as cookies para que se armazenem durante um ano no computador do usuário.

    Nota: É importante assinalar que, para colocar ou criar cookies no navegador do visitante, devemos fazê-lo antes de terem enviado os cabeçalhos de http, ou seja, antes de ter escrito qualquer texto na página. Caso contrário, poderia nos dar um erro de http headers already sent.


    Por último, veremos o código PHP para ver se detectamos as cookies no navegador de um usuário autenticado anteriormente no sistema e salvo no computador do usuário.

    //primeiro tenho que ver se o usuário está memorizado em uma cookie
    if (isset($_COOKIE["id_usuario_dw"]) && isset($_COOKIE["marca_aleatoria_usuario_dw"])){
       //Tenho cookies memorizadas
       //ademais vou comprovar que essas variáveis não estejam vazias
       if ($_COOKIE["id_usuario_dw"]!="" || $_COOKIE["marca_aleatoria_usuario_dw"]!=""){
          //Vou ver se correspondem com algum usuário
          $ssql = "select * from usuario where id_usuario=" . $_COOKIE["id_usuario_dw"] . " and cookie='" . $_COOKIE["marca_aleatoria_usuario_dw"] . "' and cookie<>''";
          $rs = mysql_query($ssql);
          if (mysql_num_rows($rs)==1){
             echo "<b>Tenho um usuário correto em uma cookie</b>";
             $usuario_encontrado = mysql_fetch_object($rs);
             echo "<br>É o usuário número " . $usuario_encontrado->id_usuario . ", de nome " . $usuario_encontrado->usuario;
             //header ("Location: conteudos_protegidos_cookie.php");
          }
       }
    }


    Como primeiro passo, comprovo se existem as cookies com o identificador do usuário e a mencionada marca aleatória. Além disso, fazemos uma comprovação adicional para ver se alguma das duas cookies contém um string vazio, porque nesse caso não estão salvas corretamente e não nos servem.

    Se tudo tiver ido bem, olhamos no banco de dado se o usuário com identificador determinado na cookie tem a marca aleatória igual que a que tinha a cookie do navegador do visitante. Ademais, na consulta no banco de dados também nos asseguramos que a marca aleatória seja distinta de "", porque então é um usuário que nunca havia pedido que se salvassem seus dados no computador.

    Se essa consulta dava um registro, é que corresponde com um usuário que havia armazenado o computador e é o usuário que estava autenticado anteriormente e salvo seu acesso.

    Conclusão

    Até aqui comentei tudo o que necessitamos saber para criar a infra-estrutura para que a página web lembre a chave ao usuário e não tenha que se autenticar cada vez que acessar o site. O código que mostramos poderia se completar com uma série de melhoras ou personalizações para adaptá-lo às nossas necessidades, mas certamente serve de guia para o interessado.

    Agora apresento o código completo da página deste exemplo:

    <?
    //conecto com o banco de dados
    $conn = mysql_connect("servidor","usuario","chave");
    //seleciono o BD
    mysql_select_db("banco de dados",$conn);

    //primeiro tenho que ver se o usuário está memorizado em uma cookie
    if (isset($_COOKIE["id_usuario_dw"]) && isset($_COOKIE["marca_aleatoria_usuario_dw"])){
       //Tenho cookies memorizadas
       //ademais vou comprovar que essas variáveis não estejam vazias
       if ($_COOKIE["id_usuario_dw"]!="" || $_COOKIE["marca_aleatoria_usuario_dw"]!=""){
          //Vou ver se correspondem com algum usuário
          $ssql = "select * from usuario where id_usuario=" . $_COOKIE["id_usuario_dw"] . " and cookie='" . $_COOKIE["marca_aleatoria_usuario_dw"] . "' and cookie<>''";
          $rs = mysql_query($ssql);
          if (mysql_num_rows($rs)==1){
             echo "<b>Tenho um usuário correto em uma cookie</b>";
             $usuario_encontrado = mysql_fetch_object($rs);
             echo "<br>É o usuário número " . $usuario_encontrado->id_usuario . ", de nome " . $usuario_encontrado->usuario;
             //header ("Location: conteudos_protegidos_cookie.php");
          }
       }
    }

    if ($_POST){
       //é que estamos recebendo dados pelo formulário de autenticação (recibo de $_POST)

       //deveria comprovar se o usuário é correto
       $ssql = "select * from usuario where usuario = '" . $_POST["usuario"] . "' and chave='" . $_POST["chave"] . "'";
       //echo $ssql;
       $rs = mysql_query($ssql);
       if (mysql_num_rows($rs)==1){
          //TUDO CORRETO!! Detectei um usuário
          $usuario_encontrado = mysql_fetch_object($rs);
          //agora devo de ver se o usuário queria memorizar sua conta nesse computador
          if ($_POST["salvar_chave"]=="1"){
             //é que pediu para memorizar o usuário
             //1) crio uma marca aleatória no registro deste usuário
             //alimentamos o gerador de aleatórios
             mt_srand (time());
             //geramos um número aleatório
             $numero_aleatorio = mt_rand(1000000,999999999);
             //2) meto a marca aleatória na tabela de usuário
             $ssql = "update usuario set cookie='$numero_aleatorio' where id_usuario=" . $usuario_encontrado->id_usuario;
             mysql_query($ssql);
             //3) agora coloco uma cookie no computador do usuário com o identificador do usuário e a cookie aleatória
             setcookie("id_usuario_dw", $usuario_encontrado->id_usuario , time()+(60*60*24*365));
             setcookie("marca_aleatoria_usuario_dw", $numero_aleatorio, time()+(60*60*24*365));
          }
          echo "Autenticado corretamente";
          //header ("Location: conteudos_protegidos_cookie.php");
          
       }else{
          echo "Falha de autenticação!";
          echo "<p><a href='prova-cookies.php'>Voltar</a>";
       }
       
    }else{
    ?>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

    <html>
    <head>
       <title>cookies para detectar usuario</title>
    </head>

    <body>

    <form action="prova-cookies.php" method="post">
    Usuario: <input type="text" name="usuario">
    <br>
    Chave: <input type="text" name="chave">
    <br>
    <input type="checkbox" name="salvar_chave" value="1"> Memorizar o usuário neste computador
    <br>
    <input type="submit" value="Entrar">
    </form>
    <br>
    <br>
    <b>Usuários válidos:</b>
    <br>
    <br>
       User: pepe
       <br>
       Chave: 1234
       <br>
       <br>
       User: juan
       <br>
       Chave: 1111

    </body>
    </html>

    <?
    }
    ?>






    Comentários do artigo
    Foram enviados 5 comentários ao artigo
    2 comentários não revisados
    3 comentários revisados:
    Realização e estrutura do banco de dados
    Por: Fabio
    12/11/08
    Olá, o site de vocês é maravilhoso! Porém, tenho uma dúvida neste artigo... estamos devenvolvendo um sistema de login muito parecido com esse, mas algo que esta nos preocupando é a parte do banco de dados, por favor, poderiam mostrar como foi realizada e como está estruturado o banco de dados desse sistema de autentificação?
    Obrigado
    Resposta para Fabio
    Por: miguel_angel-alvarez_sanchez
    12/11/08
    O banco de dados foi realizado com MySQL. Nós fizemos as tabelas com o sistema PhpMyAdmin, para nos facilitar o trabalho. Você pode ver os registros que inserimos no banco de dados através da imagem que aparece neste artigo. A partir disso, você poderá deduzir a estrutura da tabela, porém, caso não tenha ficado claro, deixo aqui o CREATE TABLE:

    CREATE TABLE `usuario_autentica_cookies` (
    `id_usuario` int(10) unsigned NOT NULL auto_increment,
    `usuario` varchar(50) NOT NULL default '',
    `clave` varchar(50) NOT NULL default '',
    `cookie` varchar(200) NOT NULL default '',
    PRIMARY KEY (`id_usuario`)
    )
    Bug no exemplo!
    Por: geladas
    16/7/12
    Olá Pessoal, tudo bem?

    Parabéns pelo post de autenticação por cookies.

    Porem o exemplo do manual está com bug: http://www.criarweb.com/artigos/exemplos/php/prueba-cookies.php

    O que pode estar acontecendo?

    Abraços,

    Thiago.

  • Usuários :    login / registro

    Manuais relacionados
    Categorias relacionadas
    O autor

    Home | Sobre nós | Copyright | Anuncie | Entrar em contato