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
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
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`)
)