Opa opa opa! Vamos continuar hoje com a terceira parte do nosso tutorial de “Criando um sistema de logins com classe no PHP”…
Já passamos vitoriosos pela Parte 1 e Parte 2 e hoje vamos fazer o método que usaremos para verificar se um usuário está logado e o método que usaremos para deslogar o usuário… A boa notícia é que depois da aula de hoje a classe estará pronta para vocês usarem em vossos sites, lembrando sempre que o importante aqui é que vocês aprendam como fazer e não apenas copiem o código e usem.
Vamos começar fazendo uma correção que o Leo Baiano sugeriu no método validaUsuario() criado na Parte 1… A mudança vai acontecer entre a linha 87 e a linha 96:
// Procura por usuários com o mesmo usuário e senha
$sql = "SELECT COUNT(*)
FROM `{$this->bancoDeDados}`.`{$this->tabelaUsuarios}`
WHERE
`{$this->campos['usuario']}` = '{$usuario}'
AND
`{$this->campos['senha']}` = '{$senha}'";
$query = mysql_query($sql);
if ($query) {
$total = mysql_result($query, 0);
Mudaremos a consulta e outras três linhas depois:
// Procura por usuários com o mesmo usuário e senha
$sql = "SELECT COUNT(*) AS total
FROM `{$this->bancoDeDados}`.`{$this->tabelaUsuarios}`
WHERE
`{$this->campos['usuario']}` = '{$usuario}'
AND
`{$this->campos['senha']}` = '{$senha}'";
$query = mysql_query($sql);
if ($query) {
$total = mysql_result($query, 0, 'total');
// Limpa a consulta da memória
mysql_free_result($query);
Essa mudança foi necessária por causa de um probleminha com a função mysql_result() que tem dificuldades de identificar qual resultado nós queremos… Com esse ajuste tudo irá funcionar perfeitamente.
Agora nós iremos começar a criar o método que verifica se há um usuário logado… Ele irá retornar TRUE quando um usuário estiver logado e retornará FALSE em qualquer situação que indique que não há um usuário logado, por isso precisamos verificar todas as possibilidades:
/**
* Verifica se há um usuário logado no sistema
*
* @return boolean - Se há um usuário logado ou não
*/
function usuarioLogado() {
// Continuaremos aqui...
}
Primeiro nós verificamos a necessidade de iniciar a sessão e lógo após isso iremos verificar se existe o valor “logado” na sessão:
// Inicia a sessão?
if ($this->iniciaSessao AND !isset($_SESSION)) {
session_start();
}
// Verifica se não existe o valor na sessão
if (!isset($_SESSION[$this->prefixoChaves . 'logado']) OR !$_SESSION[$this->prefixoChaves . 'logado']) {
return false;
}
Pra quem não lembra, esse valor $this->prefixoChaves . ‘logado’ foi criado pelo método logaUsuario().
Agora nós precisamos verificar (caso seja necessário) o cookie que contém as informações (usuário, IP e navegador) do usuário para ver se elas batem com o que está armazenado no cookie:
// Faz a verificação do cookie?
if ($this->cookie) {
// Verifica se o cookie não existe
if (!isset($_COOKIE[$this->prefixoChaves . 'token'])) {
return false;
} else {
// Continuaremos aqui...
}
}
Caso haja o cookie, precisamos criar novamente uma string encriptada contendo as informações do usuário para checar com o valor salvo no cookie:
// Monta o valor do cookie
$valor = join('#', array($_SESSION[$this->prefixoChaves . 'usuario'], $_SERVER['REMOTE_ADDR'], $_SERVER['HTTP_USER_AGENT']));
// Encripta o valor do cookie
$valor = sha1($valor);
// Verifica o valor do cookie
if ($_COOKIE[$this->prefixoChaves . 'token'] !== $valor) {
return false;
}
Feita a verificação do cookie sabemos que, depois disso tudo, o usuário está logado e podemos retornar true e fechar o método..
// A sessão e o cookie foram verificados, há um usuário logado return true;
Terminamos o método que informa se há um usuário logado, agora vamos começar o método que fará o logout do usuário:
/**
* Faz logout do usuário logado
*
* @return boolean
*/
function logout() {
// Continuaremos aqui...
}
O primeiro passo do logout é iniciar a sessão e remover todos os valores da sessão…
// Inicia a sessão?
if ($this->iniciaSessao AND !isset($_SESSION)) {
session_start();
}
// Tamanho do prefixo
$tamanho = strlen($this->prefixoChaves);
// Destroi todos os valores da sessão relativos ao sistema de login
foreach ($_SESSION AS $chave=>$valor) {
// Remove apenas valores cujas chaves comecem com o prefixo correto
if (substr($chave, 0, $tamanho) == $this->prefixoChaves) {
unset($_SESSION[$chave]);
}
}
Repare que entre a linha 236 e 242 fizemos uma coisa interessante: removemos da sessão apenas os valores que pertencerem ao nosso sistema de login… Muita gente usa um simples session_destroy() para acabar com a sessão, mas se o seu site salvar valores na sessão não podemos simplesmente apagá-los, concorda?
Por isso nós fazemos uma verificação a mais, que checa se ainda existem valores na sessão e [caso não exista nada] usamos o session_destroy() e depois removemos o cookie que identifica qual sessão é de qual visitante:
// Destrói asessão se ela estiver vazia
if (count($_SESSION) == 0) {
session_destroy();
// Remove o cookie da sessão se ele existir
if (isset($_COOKIE['PHPSESSID'])) {
setcookie('PHPSESSID', false, (time() - 3600));
unset($_COOKIE['PHPSESSID']);
}
}
Agora o último passo do logout é remover o cookie que armazena as informações do visitante:
// Remove o cookie com as informações do visitante
if ($this->cookie AND isset($_COOKIE[$this->prefixoChaves . 'token'])) {
setcookie($this->prefixoChaves . 'token', false, (time() - 3600), '/');
unset($_COOKIE[$this->prefixoChaves . 'token']);
}
Terminando o método poremos retornar o valor booleano (true ou false) que informa se o usuário foi deslogado com sucesso… Existe forma melhor de fazer isso do que verificando se não há um usuário logado?
// Retorna SE não há um usuário logado return !$this->usuarioLogado();
E a nossa classe de controle e gerencia de usuários logados está completa!
Espero realmente que tenham gostado e aprendido com essa sequencia de tutoriais… Pro fim de semana criarei um outro tópico apenas mostrando como usar a classe criada aqui e aguardem a Parte 4 onde iremos implementar alguns métodos adicionais na classe Usuario para termos a funcionalidade “Lembrar minha senha”.
Se o retorno dessa Parte 3 for satisfatório (leia-se, muitos comentários) já começarei a planejar a Parte 5, onde iremos criar o sistema de niveis de acesso em uma classe adicional que estenderá a classe Usuario… Comentem e aguardem!
Pra quem quiser, o download do script completo:
- Parte 1 » PHP, RAR ou Pastie
- Parte 2 » PHP, RAR ou Pastie (Já inclui os códigos da Parte 1)
- Parte 3 » PHP, RAR ou Pastie (Já inclui os códigos da Parte 1 e Parte 2)
Não deixem de dar uma olhada nas outras partes:
- Criando um sistema de logins com classe no PHP – Parte 1
- Criando um sistema de logins com classe no PHP – Parte 2
Abraços e até a próxima!
Você também vai gostar de ler:
- Criando um sistema de logins com classe no PHP – Parte 2
- Criando um sistema de logins com classe no PHP – Parte 1
- Criando um sistema de logins com classe no PHP – Parte 4
- Sistema de logins com classe no PHP – Como usar?
- Criando um sistema de login com PHP e MySQL
Postado em Artigos, MySQL, PHP, Tutoriais
Com as tags Ajuste, Classe, Código, comentários, Cookie, Download, Funcionalidade, Login, MySQL, Navegador, PHP, PHPS, POO, Script, Scripts, Segurança, Senha, Sessão, Session, Sistema, SQL, Tutoriais, Tutorial
Escrito por Thiago Belem
Gostou desse artigo?
Não se esqueça de assinar o RSS e divulgue-o para o mundo:

Opa, no aguardo da 5 parte! rs
Vai ter? ^^
Parabéns, assim como a galera falou, também aprendi bastante sobre POO!
Obrigado!
Muito bom. Esse tutorial ajudará muitas pessoas, assim como eu, a entender melhor o PHP OO.
Parabéns pelo trabalho.
Um grande abraço.
E que venha a Parte 5!
Thiago, me tira uma dúvida aqui:
Eu estou tentando criar uma classe para o cadastro do usuário no sistema, parecida com a sua de fazer o login dele, mas como faz tempo que eu não mecho com POO, acabei travando… =/
Em certo ponto de minha classe, eu preciso fazer uma validação dos dados do form. O problema é que são muitos, cerca de 20 (+) campos…
Tem alguma forma mais prática de se pegar esses dados, ou eu tenho de passar todos eles por parâmetro para a classe, para poder manipulá-los?
@Gabriel
Procure sobre a função “get_func_args()”… Abraços
Thiago… eu consegui resolver o lance da classe de conexão… eu instanciei ela normalmente dentro da classe e tá funcionando direitinho…
O problema que estou tendo agora é com os Cookies.
Ao seta-lo como true, na linha 56 aprox., ele passa a atrapalhar na checagem do usuário online.
var $cookie = true;if ( $userClass->usuarioLogado() === false ) {...}Na expressão acima, mesmo que o usuário tenha sido logado corretamente, e as Sessions criadas, ele age como se não estivesse logado. Se eu setar a variável $cookie como false ele passa a funcionar direitinho.
Eu estou testando localmente, tem alguma configuração a ser feita no php para ele rodar os cookies, ou tem algum bug nessa parte do código???
@Gabriel Lau
Quando eu fiz testes locais funcionou tudo perfeitamente… Mas estou postando a Parte 4 da sequencia agora e nela eu fiz algumas melhorias na classe toda, inclusive nos cookies, pode ser que resolva o seu problema.
Você tem alguma lógica para criar um site parecido com Joomla, onde o cliente através do administrador monta menu, conteúdo, cria, edita e exclui? Abraço.
@Thiago
(In)felizmente meus tutoriais e artigos são sobre pequenos sistemas e códigos que visam (principalmente) mostrar como cada parte de um sistema funciona e ajudar as pessoas a fazerem sistemas melhores.. Isso tudo é exatamente o contrário do Joomla, que permite que a pessoa faça um site inteiro sem se preocupar com as pequenas partes do sistema.
Olá Thiago… queria sugerir um tema pra um outro post seu. Seria sobre a opção “Esqueci minha senha” que existe em muitos sistemas de login.
Eu gostaria mesmo é de algumas dicas sobre o assunto pois, parece simples, mas esta action também precisa de segurança. Eu já vi várias opções, em vários sites… mas gostaria de saber que tipo de dados deve-se pedir para garantir que nenhum usuário mal intencionado possa burlar a conta de outro usuário.
@Gabriel
Já estou preparando algumas melhorias para a classe, essa sua idéia pode entrar na próxima parte junto com o “Lembrar minha senha” (na hora do login).
Olá Thiago… ficou muuuito bacana essa sua aplicação para login usando classes… gostei mto mesmo… mas tenho uma dúvida:
Eu utilizo uma classe para conexão com o banco de dados que achei nesse site aqui: Webartz (Classe mysql)
Na sua classe, você inseriu dados de conexão com o banco manualmente, mas não teria uma forma de se usar esta classe de conexão (que eu mostrei) para não ter que ficar repetindo código?
@Gabriel
Acho que você se enganou… Não fiz conexão MySQL na minha classe.
Eu apenas defini o nome do banco de dados e o nome da tabela onde ficam as informações sobre os usuários… Mas, novamente, não tem nenhuma conexão MySQL nessa classe.
Abraços
Tem razão Thiago, eu me confundi acabei perguntando outra coisa.
O que eu queria saber na verdade era se tinha como eu utilizar a minha classe de conexão com o banco, dentro da sua classe…
Faz tempo que eu não mecho com POO, não lembro mais dessas coisas de hierarquia e talz…
Show de bola, continua ai!!
Sucesso
Thiago, muito bom o tutorial.
Primeira vez que vejo o PHP sem utilizado com classes.
Espero que continue.
Abraços.
ps: aqui embaixo do seu blog está escrito Artigos Popoulares
Aê parceiro, continua que a parada ta ficando boa!
Sensacional o blog, já ajudou muitas vezes!
que venha o próximo tutorial.
Thiago ficou muito bom, parabéns! Acho que mais didático é impossível rsr. Gostei da maneira como você comenta o código, o interessante é como alguns IDEs respondem a essa prática, por exemplo, o NetBeans passa a indicar todas as informações da classe, método, propriedade etc. relacionando com tudo que foi comentado… Irei adotar essa prática
Aguardo as próximas partes! Abraço.
Aqui fica mais um incentivo para o próximo passo
Muito bom o blog, tu ta de parabéns, abraço!
Realmente muito bom…
estou esperando o proximo tutorial ensinando a usar essa classe!!
parabens Thiado Belem.!
Muito bom, parabéns!
É possível que você adicione a funcionalidade de expirar a sessão com um determinado tempo sem uso?
Abraço!
@Thiago
A sessão já expira automaticamente se não houver refresh… Esse é um comportamento padrão do PHP.
@Gabriel
Sim Gabriel, você pode usar sem problemas… Você precisaria apenas instanciar a classe dentro dos métodos da minha classe e usar a sua classe para fazer as consultas..