Recuperação de Senha com Hashing em PHP e Conexão com Banco de Dados
Este tutorial foi criado com base na tabela de usuários do banco de dados de um sistema, utilizando a tabela users
. A ideia é explicar como implementar um sistema de recuperação de senha usando PHP, com segurança, e fazer referência à estrutura específica do banco de dados que você estará utilizando.
Estrutura da Tabela `users`
A seguir, apresentamos a estrutura da tabela users
no banco de dados que está sendo usada para este tutorial. Se a sua tabela for diferente, você precisará ajustar os campos no código conforme necessário.
CREATE TABLE `users` (
`user_id` bigint(20) UNSIGNED NOT NULL,
`email` varchar(320) NOT NULL,
`password` varchar(128) DEFAULT NULL,
`name` varchar(64) NOT NULL,
`billing` text DEFAULT NULL,
`api_key` varchar(32) DEFAULT NULL,
`token_code` varchar(32) DEFAULT NULL,
`twofa_secret` varchar(16) DEFAULT NULL,
`anti_phishing_code` varchar(8) DEFAULT NULL,
`one_time_login_code` varchar(32) DEFAULT NULL,
`pending_email` varchar(128) DEFAULT NULL,
`email_activation_code` varchar(32) DEFAULT NULL,
`lost_password_code` varchar(32) DEFAULT NULL, -- Este campo será usado para armazenar o token de recuperação
`type` tinyint(4) NOT NULL DEFAULT 0,
`status` tinyint(4) NOT NULL DEFAULT 0,
`plan_id` varchar(16) NOT NULL DEFAULT '',
`plan_expiration_date` datetime DEFAULT NULL,
`plan_settings` text DEFAULT NULL,
`payment_subscription_id` varchar(64) DEFAULT NULL,
`payment_processor` varchar(16) DEFAULT NULL,
`payment_total_amount` float DEFAULT NULL,
`payment_currency` varchar(4) DEFAULT NULL,
`language` varchar(32) DEFAULT 'english',
`datetime` datetime DEFAULT NULL,
`last_activity` datetime DEFAULT NULL,
`total_logins` int(11) DEFAULT 0,
`ip` varchar(64) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
O código abaixo foi desenvolvido considerando a estrutura desta tabela, especialmente os campos:
email
- O campo que armazena o e-mail do usuário.password
- O campo onde a senha é armazenada, utilizando hashing.lost_password_code
- O campo onde será armazenado o token gerado para a recuperação de senha.
O que é Hashing de Senha?
O hashing é uma técnica que transforma uma senha em uma sequência fixa de caracteres aparentemente aleatórios. Esse processo é irreversível, ou seja, não é possível recuperar a senha original a partir do hash. A função password_hash
no PHP cria esse hash usando o algoritmo Bcrypt.
<?php
// Exemplo de como criar um hash de senha
$senha = "minha_senha_segura";
$hash = password_hash($senha, PASSWORD_BCRYPT);
echo $hash; // Exibe algo como "$2y$10$..."
?>
Implementando a Recuperação de Senha
Agora, vamos mostrar como implementar o sistema de recuperação de senha, considerando a tabela users
do seu banco de dados.
Passo 1: Criando o Formulário de Solicitação
Primeiro, crie um arquivo chamado solicitar_recuperacao.php
com um formulário simples para o usuário inserir seu e-mail:
<form method="post" action="processar_solicitacao.php">
<label>E-mail:</label><br>
<input type="email" name="email" required style="width: 100%; padding: 8px; margin-bottom: 10px;">
<br>
<button type="submit" style="background-color: #007bff; color: white; border: none; padding: 10px 15px; cursor: pointer;">Enviar Solicitação</button>
</form>
Passo 2: Processando a Solicitação e Enviando o E-mail com o Token
No arquivo processar_solicitacao.php
, o sistema vai gerar um token único, enviar para o e-mail do usuário e salvar o token na tabela users
. Veja como:
<?php
// Conexão com o banco de dados
try {
$pdo = new PDO('mysql:host=localhost;dbname=apphostssd_seo', 'usuario', 'senha');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo 'Erro na conexão: ' . $e->getMessage();
exit;
}
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$email = $_POST['email'];
// Gerar o token único
$token = bin2hex(random_bytes(16)); // Gera um token de 16 bytes
// Verificar se o e-mail existe no banco de dados
$stmt = $pdo->prepare("SELECT * FROM users WHERE email = :email");
$stmt->execute(['email' => $email]);
$usuario = $stmt->fetch(PDO::FETCH_ASSOC);
if ($usuario) {
// Gerar um link de recuperação
$link = "https://seusite.com/redefinir_senha.php?token=$token";
// Salvar o token no banco de dados com data de expiração (1 hora)
$expiracao = date('Y-m-d H:i:s', strtotime('+1 hour'));
$stmt = $pdo->prepare("UPDATE users SET lost_password_code = :token WHERE email = :email");
$stmt->execute(['token' => $token, 'email' => $email]);
// Enviar o e-mail ao usuário
mail($email, "Redefinição de Senha", "Clique no link para redefinir sua senha: $link");
echo "Instruções enviadas para o seu e-mail.";
} else {
echo "E-mail não encontrado.";
}
}
?>
Passo 3: Redefinindo a Senha
No arquivo redefinir_senha.php
, o sistema verifica o token e permite que o usuário insira uma nova senha:
<?php
// Conexão com o banco de dados
try {
$pdo = new PDO('mysql:host=localhost;dbname=apphostssd_seo', 'usuario', 'senha');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo 'Erro na conexão: ' . $e->getMessage();
exit;
}
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$nova_senha = $_POST['senha'];
$token = $_GET['token'];
// Verificar o token
$stmt = $pdo->prepare("SELECT * FROM users WHERE lost_password_code = :token");
$stmt->execute(['token' => $token]);
$usuario = $stmt->fetch(PDO::FETCH_ASSOC);
if ($usuario) {
// Atualizar a senha no banco de dados
$hash_senha = password_hash($nova_senha, PASSWORD_BCRYPT);
$stmt = $pdo->prepare("UPDATE users SET password = :senha, lost_password_code = NULL WHERE lost_password_code = :token");
$stmt->execute(['senha' => $hash_senha, 'token' => $token]);
echo "Senha redefinida com sucesso!";
} else {
echo "Token inválido ou expirado.";
}
}
?>
O que o Desenvolvedor Deve se Atentar:
- Verifique o nome da tabela no banco de dados. Este tutorial foi criado com base na tabela
users
. Se o nome da tabela for diferente, altere o código conforme necessário. - Verifique os nomes dos campos. No caso da tabela
users
, o campo de e-mail éemail
, o campo de token élost_password_code
e o campo de senha épassword
. Se os nomes dos campos forem diferentes, altere os nomes no código. - Considere o tipo de dados para armazenar o token e os hashes. O campo de senha deve ter um tamanho suficiente para armazenar o hash gerado pelo
password_hash
, que tem 60 caracteres. O token pode ser armazenado em um campo de 32 caracteres.
Com estas etapas, você terá um sistema seguro de recuperação de senha e protegerá melhor os dados sensíveis dos seus usuários.
Precisa de Ajuda Profissional?
Se você não conseguir recuperar o acesso ao seu sistema utilizando este tutorial ou preferir uma solução segura e rápida, entre em contato conosco para um suporte especializado.