Conceitos que serão ensinados:
-
password_hash()— criptografa senha -
password_verify()— verifica senha -
Sessões PHP (
$_SESSION) -
header('Location: ...')— redirecionamento -
Nunca salvar senha em texto puro!
1 Script do banco — banco.sql
CREATE DATABASE IF NOT EXISTS auth_system
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE auth_system;
CREATE TABLE IF NOT EXISTS usuarios (
id INT AUTO_INCREMENT PRIMARY KEY,
nome VARCHAR(150) NOT NULL,
email VARCHAR(150) UNIQUE NOT NULL,
senha VARCHAR(255) NOT NULL,
nivel ENUM('admin', 'usuario') DEFAULT 'usuario',
ativo TINYINT(1) DEFAULT 1,
data_cadastro TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- IMPORTANTE: insira os usuários via cadastro.php para gerar o hash correto
-- Não insira senhas em texto puro!
2 Arquivo config.php
<?php
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', '');
define('DB_NAME', 'auth_system');
$conexao = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if ($conexao->connect_error) {
die("Erro: " . $conexao->connect_error);
}
$conexao->set_charset('utf8mb4');
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
function estaLogado() {
return isset($_SESSION['usuario_id']);
}
function exigirLogin() {
if (!estaLogado()) {
header('Location: login.php');
exit;
}
}
function usuarioLogado($conexao) {
if (!estaLogado()) return null;
$stmt = $conexao->prepare("SELECT id, nome, email, nivel FROM usuarios WHERE id = ?");
$stmt->bind_param('i', $_SESSION['usuario_id']);
$stmt->execute();
$user = $stmt->get_result()->fetch_assoc();
$stmt->close();
return $user;
}
?>
3 Arquivo cadastro.php
<?php
require_once 'config.php';
$erros = [];
$sucesso = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$nome = trim($_POST['nome'] ?? '');
$email = trim($_POST['email'] ?? '');
$senha = $_POST['senha'] ?? '';
// Validações
if (strlen($nome) < 3) $erros[] = 'Nome muito curto';
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) $erros[] = 'E-mail inválido';
if (strlen($senha) < 6) $erros[] = 'Senha deve ter pelo menos 6 caracteres';
// Verifica se e-mail já existe
if (empty($erros)) {
$stmt = $conexao->prepare("SELECT id FROM usuarios WHERE email = ?");
$stmt->bind_param('s', $email);
$stmt->execute();
if ($stmt->get_result()->num_rows > 0) {
$erros[] = 'E-mail já cadastrado';
}
$stmt->close();
}
// Cadastra
if (empty($erros)) {
$hash = password_hash($senha, PASSWORD_DEFAULT);
$stmt = $conexao->prepare(
"INSERT INTO usuarios (nome, email, senha) VALUES (?, ?, ?)"
);
$stmt->bind_param('sss', $nome, $email, $hash);
if ($stmt->execute()) {
$sucesso = 'Cadastro realizado com sucesso! Faça login.';
} else {
$erros[] = 'Erro ao cadastrar';
}
$stmt->close();
}
}
?>
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<title>Cadastro</title>
<link rel="stylesheet" href="style.css">
</head>
<body class="auth-body">
<div class="auth-card">
<div class="auth-icon">📝</div>
<h1>Criar Conta</h1>
<p class="auth-sub">Preencha os dados para se cadastrar</p>
<?php if (!empty($erros)): ?>
<div class="alert alert-error">
<?php foreach ($erros as $e): ?>
<div>⚠️ <?php echo htmlspecialchars($e); ?></div>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if ($sucesso): ?>
<div class="alert alert-success">✅ <?php echo $sucesso; ?></div>
<?php endif; ?>
<form method="POST">
<div class="form-group">
<label>Nome completo</label>
<input type="text" name="nome" required
value="<?php echo htmlspecialchars($_POST['nome'] ?? ''); ?>">
</div>
<div class="form-group">
<label>E-mail</label>
<input type="email" name="email" required
value="<?php echo htmlspecialchars($_POST['email'] ?? ''); ?>">
</div>
<div class="form-group">
<label>Senha</label>
<input type="password" name="senha" required minlength="6">
</div>
<button type="submit" class="btn-full">Cadastrar</button>
</form>
<p class="auth-footer">
Já tem conta? <a href="login.php">Faça login</a>
</p>
</div>
</body>
</html>
4 Arquivo login.php
<?php
require_once 'config.php';
if (estaLogado()) {
header('Location: painel.php');
exit;
}
$erro = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$email = trim($_POST['email'] ?? '');
$senha = $_POST['senha'] ?? '';
if (empty($email) || empty($senha)) {
$erro = 'Preencha todos os campos';
} else {
$stmt = $conexao->prepare(
"SELECT id, nome, senha, ativo FROM usuarios WHERE email = ?"
);
$stmt->bind_param('s', $email);
$stmt->execute();
$usuario = $stmt->get_result()->fetch_assoc();
$stmt->close();
if ($usuario && password_verify($senha, $usuario['senha'])) {
if (!$usuario['ativo']) {
$erro = 'Conta desativada';
} else {
$_SESSION['usuario_id'] = $usuario['id'];
$_SESSION['usuario_nome'] = $usuario['nome'];
header('Location: painel.php');
exit;
}
} else {
$erro = 'E-mail ou senha incorretos';
}
}
}
?>
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<title>Login</title>
<link rel="stylesheet" href="style.css">
</head>
<body class="auth-body">
<div class="auth-card">
<div class="auth-icon">🔒</div>
<h1>Entrar</h1>
<p class="auth-sub">Acesse sua conta</p>
<?php if ($erro): ?>
<div class="alert alert-error">⚠️ <?php echo htmlspecialchars($erro); ?></div>
<?php endif; ?>
<form method="POST">
<div class="form-group">
<label>E-mail</label>
<input type="email" name="email" required autofocus
value="<?php echo htmlspecialchars($_POST['email'] ?? ''); ?>">
</div>
<div class="form-group">
<label>Senha</label>
<input type="password" name="senha" required>
</div>
<button type="submit" class="btn-full">Entrar</button>
</form>
<p class="auth-footer">
Não tem conta? <a href="cadastro.php">Cadastre-se</a>
</p>
</div>
</body>
</html>
5 Arquivo painel.php
<?php
require_once 'config.php';
exigirLogin();
$usuario = usuarioLogado($conexao);
?>
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<title>Painel</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<div class="painel-card">
<div class="user-avatar">
<?php echo strtoupper(substr($usuario['nome'], 0, 1)); ?>
</div>
<h1>Olá, <?php echo htmlspecialchars($usuario['nome']); ?>!</h1>
<p class="user-email">📧 <?php echo htmlspecialchars($usuario['email']); ?></p>
<p class="user-nivel">
Nível: <strong><?php echo $usuario['nivel']; ?></strong>
</p>
<div class="painel-actions">
<a href="logout.php" class="btn-logout">🚪 Sair</a>
</div>
</div>
</div>
</body>
</html>
6 Arquivo logout.php
<?php
session_start();
session_destroy();
header('Location: login.php');
exit;
?>
7 Arquivo style.css
/* style.css - Sistema de Login */
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Segoe UI', sans-serif;
background: linear-gradient(135deg, #1e3a8a 0%, #312e81 100%);
min-height: 100vh;
color: #1f2937;
}
/* Auth */
body.auth-body {
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.auth-card {
background: white;
padding: 45px 35px;
border-radius: 16px;
width: 100%;
max-width: 420px;
box-shadow: 0 25px 60px rgba(0,0,0,0.4);
border-top: 4px solid #fbbf24;
text-align: center;
}
.auth-icon {
font-size: 3rem;
margin-bottom: 15px;
}
.auth-card h1 {
color: #1e3a8a;
font-size: 1.6rem;
margin-bottom: 6px;
}
.auth-sub {
color: #6b7280;
font-size: 0.9rem;
margin-bottom: 25px;
}
.form-group {
display: flex;
flex-direction: column;
margin-bottom: 18px;
text-align: left;
}
.form-group label {
font-size: 0.82rem;
font-weight: 600;
color: #1e3a8a;
margin-bottom: 6px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.form-group input {
padding: 13px 16px;
border: 2px solid #e5e7eb;
border-radius: 8px;
font-size: 1rem;
font-family: inherit;
transition: all 0.2s;
}
.form-group input:focus {
outline: none;
border-color: #1e3a8a;
box-shadow: 0 0 0 3px rgba(30, 58, 138, 0.1);
}
.btn-full {
width: 100%;
padding: 14px;
background: #1e3a8a;
color: white;
border: none;
border-radius: 8px;
font-size: 0.95rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 1.5px;
cursor: pointer;
font-family: inherit;
transition: all 0.2s;
margin-top: 10px;
}
.btn-full:hover {
background: #1e40af;
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(30, 58, 138, 0.3);
}
.auth-footer {
margin-top: 20px;
color: #6b7280;
font-size: 0.9rem;
}
.auth-footer a {
color: #1e3a8a;
font-weight: 600;
text-decoration: none;
}
.auth-footer a:hover {
text-decoration: underline;
}
/* Alertas */
.alert {
padding: 12px 16px;
border-radius: 8px;
margin-bottom: 20px;
text-align: left;
font-size: 0.9rem;
line-height: 1.6;
}
.alert-error {
background: #fee2e2;
color: #991b1b;
border-left: 4px solid #ef4444;
}
.alert-success {
background: #d1fae5;
color: #065f46;
border-left: 4px solid #10b981;
}
/* Painel */
.container {
max-width: 600px;
margin: 0 auto;
padding: 60px 20px;
}
.painel-card {
background: white;
padding: 50px 40px;
border-radius: 16px;
text-align: center;
box-shadow: 0 25px 60px rgba(0,0,0,0.3);
}
.user-avatar {
width: 90px;
height: 90px;
background: linear-gradient(135deg, #1e3a8a, #312e81);
color: #fbbf24;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 2.5rem;
font-weight: 800;
margin: 0 auto 20px;
}
.painel-card h1 {
color: #1e3a8a;
margin-bottom: 10px;
}
.user-email {
color: #6b7280;
margin-bottom: 8px;
}
.user-nivel {
color: #6b7280;
margin-bottom: 25px;
}
.btn-logout {
display: inline-block;
padding: 12px 30px;
background: #ef4444;
color: white;
text-decoration: none;
border-radius: 8px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 1px;
font-size: 0.85rem;
transition: all 0.2s;
}
.btn-logout:hover {
background: #dc2626;
transform: translateY(-2px);
}
8-index.php
<?php
// index.php - Redireciona para a página de login
require_once 'config.php';
if (estaLogado()) {
header('Location: painel.php');
} else {
header('Location: login.php');
}
exit;
?>

