Blog ComercialWeb - São Paulo - SP
E-mail: [email protected]
Atualizado: 11/10/2025

Como criar sistema de login em PHP com password_hash e sessões

Login em PHP com password_hash e sessões

Aprenda a construir um sistema de login em PHP com password_hash/password_verify, sessões seguras, proteção CSRF e logout. Os exemplos usam PDO e prepared statements para evitar SQL Injection.

Estrutura da tabela de usuários

CREATE TABLE users (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(191) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP );

Dica: use utf8mb4 no banco, email unique e índices conforme necessidade.

Setup de sessão segura (antes de qualquer saída)

<?php
session_set_cookie_params([
'lifetime' => 0,
'path' => '/',
'domain' => '',
'secure' => isset($_SERVER['HTTPS']),
'httponly' => true,
'samesite' => 'Lax' ]);
session_start();
session_regenerate_id(true);

Cadastro: salvando com password_hash

<?php
$pdo = new PDO('mysql:host=localhost;dbname=app;charset=utf8mb4', 'user', 'pass', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
$pass = $_POST['password'] ?? '';
if ($email && strlen($pass) >= 8) {
$hash = password_hash($pass, PASSWORD_DEFAULT);
$stmt = $pdo->prepare('INSERT INTO users (email, password_hash) VALUES (:e, :h)');
$stmt->execute([':e' => $email, ':h' => $hash]);
echo 'Cadastrado!';
}

CSRF: gerando e validando token

<?php
function csrf_token() {
if (empty($_SESSION['csrf'])) {
$_SESSION['csrf'] = bin2hex(random_bytes(32));
}
return $_SESSION['csrf']; }
function csrf_check($token) {
return hash_equals($_SESSION['csrf'] ?? '', $token); }

Inclua o token com <input type="hidden" name="csrf" value="<?= csrf_token() ?>"> e valide no POST.

Login: password_verify, sessão e regeneração de ID

<?php
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
$pass = $_POST['password'] ?? '';
if (!csrf_check($_POST['csrf'] ?? '')) { die('CSRF inválido'); }
$stmt = $pdo->prepare('SELECT id, password_hash FROM users WHERE email = :e LIMIT 1');
$stmt->execute([':e' => $email]);
$u = $stmt->fetch();
if ($u && password_verify($pass, $u['password_hash'])) {
$_SESSION['uid'] = $u['id'];
session_regenerate_id(true);
header('Location: /area-restrita.php'); exit;
}
echo 'Credenciais inválidas';

Logout

<?php
session_start();
$_SESSION = [];
if (ini_get('session.use_cookies')) {
$p = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000, $p['path'], $p['domain'], $p['secure'], $p['httponly']);
}
session_destroy();

Remova os dados da sessão, destrua o cookie e finalize a sessão no servidor.

Boas práticas

  • Use HTTPS e cookies HttpOnly/SameSite.
  • Política mínima de senha: 8+ caracteres, incentivo a passphrases.
  • Bloqueie tentativas excessivas (rate limit/lockout por IP/usuário).
  • Guarde segredos e DSN em variáveis de ambiente.

Perguntas frequentes

Por que usar password_hash em vez de MD5/SHA1?
password_hash usa salt e custo (ex.: bcrypt/argon2), muito mais seguro do que hashes simples.
Como manter a sessão segura?
Defina cookies HttpOnly/SameSite, use HTTPS e regenere o ID após o login.
Como implementar "lembrar-me" com segurança?
Gere token aleatório, armazene apenas o hash com expiração e invalide no logout/troca de senha.
Para que serve o token CSRF?
Evita submissões forjadas. Gere um token por sessão e valide em cada POST sensível.
Fonte: Redação


Mais Lidos

Ferramentas úteis

Precisa gerar senhas, validar CPF/CNPJ ou criar QR Code? Acesse nossos Geradores e Validadores Online.