Sessões e sistema de login

Os cookies armazenam dados no navegador do usuário; as sessões, no servidor. Estado de login, carrinhos de compras, sinalizadores de permissão — qualquer dado que você não queira que o usuário altere deve ficar em uma sessão. Ao final desta lição, você terá criado seu primeiro sistema de login.

1. O que é uma sessão?

Uma sessão é uma área de armazenamento privada no servidor, criada para cada usuário. O navegador armazena apenas um cookie com o ID da sessão; todos os dados reais permanecem no lado do servidor:

TEXT
Cookie:                          Session:
Only holds the Session ID        Stores the actual data (username, role, cart...)
┌──────────────┐                ┌──────────────────────┐
│ PHPSESSID    │  ──match──→   │ user: John            │
│ abc123       │                │ login: true           │
└──────────────┘                │ cart: [3 items]       │
   In the browser               │ role: admin           │
                                └──────────────────────┘
                                     On the server
💡 Dica: Sessão x Cookie: os cookies ficam armazenados no navegador (são visíveis e podem ser alterados pelo usuário); as sessões ficam no servidor (são seguras). No entanto, as sessões dependem dos cookies para transmitir o ID da sessão — se o usuário bloquear os cookies, as sessões são interrompidas.


2. session_start() — Iniciando uma sessão

É necessário chamar session_start() antes de utilizar qualquer funcionalidade de sessão. Essa função realiza duas tarefas:

  1. Se o navegador enviar um cookie de ID de sessão → carregar os dados correspondentes do servidor
  2. Se nenhum cookie for encontrado → criar uma nova sessão, gerar um novo ID e enviar um cookie
PHP
<?php
// session_start() must come before any HTML output
session_start();

// Store data
$_SESSION['username'] = "John";
$_SESSION['login_time'] = date("Y-m-d H:i:s");

// Read data
echo "Welcome, {$_SESSION['username']}!";
echo "Logged in at: {$_SESSION['login_time']}";
?>
🔥 Erro comum: session_start() deve ser chamado antes de qualquer saída — seja um echo, HTML bruto ou até mesmo um espaço isolado antes da tag <?php. Caso contrário, você receberá o temido erro headers already sent. Coloque-o bem no início do seu arquivo.


3. $_SESSION — Use-o como qualquer array

PHP
<?php
session_start();

// Store any PHP data type
$_SESSION['user'] = [
    'id'   => 101,
    'name' => 'John',
    'role' => 'member'
];
$_SESSION['cart'] = [
    ['name' => 'PHP Tutorial', 'price' => 39.90, 'qty' => 2],
    ['name' => 'MySQL Basics', 'price' => 29.90, 'qty' => 1],
];

// Read
echo $_SESSION['user']['name'];  // John

// Remove a single session variable
unset($_SESSION['cart']);

// Update
$_SESSION['user']['role'] = 'admin';
?>

▶ Exemplo: Um carrinho de compras baseado em sessão

PHP
<?php
session_start();

// Initialize the cart
if (!isset($_SESSION['cart'])) {
    $_SESSION['cart'] = [];
}

// Add an item
if (isset($_POST['add'])) {
    $item = $_POST['add'];
    $_SESSION['cart'][$item] = ($_SESSION['cart'][$item] ?? 0) + 1;
}

echo "<h3>Your Cart</h3>";
foreach ($_SESSION['cart'] as $item => $qty) {
    echo "{$item} × {$qty}<br>";
}
?>
<form method='POST'>
    <button name='add' value='PHP Tutorial'>Add PHP Tutorial</button>
    <button name='add' value='MySQL Basics'>Add MySQL Basics</button>
</form>
▶ Experimente

4. Criação de um sistema de login

▶ Exemplo: Sistema completo de login

PHP
<?php
// login.php — Login System
session_start();

// Predefined test users (in a real project, these live in a database)
$users = [
    'admin' => '123456',
    'john' => 'password123',
];

$error = '';

// Already logged in? Redirect to profile
if (isset($_SESSION['user'])) {
    header("Location: profile.php");
    exit;
}

// Handle login request
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $username = trim($_POST['username'] ?? '');
    $password = $_POST['password'] ?? '';

    if (isset($users[$username]) && $users[$username] === $password) {
        // Credentials verified — store user in session
        $_SESSION['user'] = [
            'username'    => $username,
            'login_time'  => date("Y-m-d H:i:s"),
            'last_active' => time(),
        ];
        
        // Redirect to profile page
        header("Location: profile.php");
        exit;
    } else {
        $error = "Invalid username or password";
    }
}
?>

<h3>Login</h3>
<?php if ($error): ?>
    <p style="color:red"><?= htmlspecialchars($error) ?></p>
<?php endif; ?>

<form method="POST" action="">
    <p>
        <label>Username:</label>
        <input type="text" name="username" required>
    </p>
    <p>
        <label>Password:</label>
        <input type="password" name="password" required>
    </p>
    <button type="submit">Log In</button>
</form>
<p style="color:#888">Test account: admin / 123456</p>
▶ Experimente
PHP
<?php
// profile.php — Profile Page (requires login)
session_start();

// Not logged in? Redirect to login
if (!isset($_SESSION['user'])) {
    header("Location: login.php");
    exit;
}

$user = $_SESSION['user'];
?>

<h2>Profile</h2>
<p>Username: <?= htmlspecialchars($user['username']) ?></p>
<p>Logged in at: <?= $user['login_time'] ?></p>

<a href="logout.php">Log Out</a>

(1) Sair da conta

PHP
<?php
// logout.php
session_start();

// Option 1: Clear only the user data
unset($_SESSION['user']);

// Option 2: Wipe the entire session
session_unset();    // Clear the $_SESSION array
session_destroy();  // Delete the server-side session file

// Redirect to login
header("Location: login.php");
exit;
?>
Operação Função O que faz
Remover um único item unset($_SESSION['key']) Exclui uma chave específica
Limpar todas as variáveis session_unset() Esvazia $_SESSION
Excluir arquivo de sessão session_destroy() Remove os dados de sessão do lado do servidor
Excluir cookie setcookie(session_name(), '', time()-3600, '/') Remove o cookie PHPSESSID do navegador
💡 Dica: A sequência padrão de logout: session_unset()session_destroy() → excluir o cookie PHPSESSID → redirecionar para a página de login.


5. O ciclo de vida da sessão

TEXT
User visits for the first time → PHP creates a session file (e.g., sess_abc123)
                ↓
          Data is written to $_SESSION
                ↓
          Cookie sent: PHPSESSID=abc123 to the browser
                ↓
Next visit → Browser sends PHPSESSID=abc123
                ↓
          PHP finds sess_abc123, loads data into $_SESSION
                ↓
... User leaves (closes browser or is idle for a long time) ...
                ↓
Garbage collection → Expired session files are deleted

Por padrão, as sessões expiram após 24 minutos (session.gc_maxlifetime = 1.440 segundos em php.ini). A contagem começa a partir da hora da última modificação do arquivo, e não da última atividade do usuário.


6. Configuração de segurança da sessão

PHP
<?php
// Configure before session_start()
ini_set('session.cookie_httponly', 1);    // JS can't read the session cookie (XSS protection)
ini_set('session.cookie_secure', 1);      // HTTPS only (required for production)
ini_set('session.cookie_samesite', 'Lax'); // CSRF mitigation
ini_set('session.use_strict_mode', 1);    // Reject uninitialized session IDs

session_start();
?>
💡 Dica: session.use_strict_mode = 1 impede que invasores forjem um ID de sessão. Se um invasor inventar um ID inexistente, o PHP o rejeita e cria uma nova sessão.


7. Cookies x Sessões: uma visão geral

Cookie Sessão
Localização dos dados Navegador do usuário Servidor
Segurança Baixa (o usuário pode visualizar/editar) Alta (o usuário nunca vê os dados)
Capacidade 4 KB Ilimitada (limitada apenas pelo espaço em disco do servidor)
Desempenho Enviado a cada solicitação Sem custo de largura de banda (consulta no lado do servidor)
Dependência Autônomo Depende de cookies (para o ID da sessão)
Ideal para Preferências, modo simplificado Login, permissões, carrinhos de compras

❓ Perguntas Frequentes

P: A sessão desaparece quando fecho o navegador? R: Os dados da sessão ainda existem no servidor (aguardando a coleta de lixo), mas o cookie PHPSESSID no navegador geralmente desaparece quando o navegador é fechado. Na próxima vez que você abrir o navegador, não haverá um ID de sessão, então o PHP cria uma sessão totalmente nova.

P: Se vários usuários fizerem login ao mesmo tempo, suas sessões interferem entre si? R: Não. Cada usuário tem sua própria sessão com um ID de sessão exclusivo. $_SESSION pertence sempre ao usuário atual — não há interferência entre elas.

P: As sessões funcionam se o usuário tiver desativado os cookies? R: Não por padrão, pois o ID da sessão é transmitido por meio de um cookie. É possível transmiti-lo pela URL (PHPSESSID=abc123), mas isso é muito inseguro — o ID da sessão acaba ficando no histórico do navegador, nos favoritos e nos logs do servidor.

📖 Resumo

📝 Exercícios

  1. Implemente o sistema completo de login dos exemplos acima (login.php → profile.php → logout.php).
  2. Adicione um recurso “Alterar senha” à página de perfil (verifique a validade em relação à matriz de usuários predefinida).
  3. Implementar um acesso simples baseado em funções: somente usuários com role === 'admin' podem ver o link “Painel de Administração” na página.
Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%