Sessions e cookies no PHP
1. Fundamentos de Cookies no PHP
1.1. O que são cookies e como funcionam no protocolo HTTP
Cookies são pequenos arquivos de texto armazenados no navegador do cliente, enviados pelo servidor através do cabeçalho HTTP Set-Cookie. No PHP, os cookies permitem manter estado entre requisições HTTP, que por natureza são stateless. Cada cookie contém um par nome-valor, além de metadados como domínio, path e data de expiração.
1.2. Criando e lendo cookies com setcookie() e $_COOKIE
A função setcookie() define um cookie que será enviado ao navegador. O array superglobal $_COOKIE permite acessar os cookies recebidos na requisição atual.
<?php
// Criando um cookie que expira em 1 hora
setcookie('usuario', 'joao', time() + 3600, '/');
// Lendo o cookie na próxima requisição
if (isset($_COOKIE['usuario'])) {
echo "Bem-vindo de volta, " . htmlspecialchars($_COOKIE['usuario']);
}
?>
1.3. Parâmetros essenciais: expiração, path, domínio e secure/httponly
<?php
setcookie(
'preferencia_tema', // nome
'escuro', // valor
time() + 86400 * 30, // expira em 30 dias
'/app/', // path - disponível apenas em /app/
'meusite.com', // domínio
true, // secure - apenas HTTPS
true // httponly - inacessível via JavaScript
);
?>
2. Manipulação Avançada de Cookies
2.1. Cookies com arrays e serialização de dados
<?php
// Armazenando array serializado
$preferencias = [
'idioma' => 'pt-BR',
'fuso' => 'America/Sao_Paulo',
'notificacoes' => true
];
setcookie('preferencias', serialize($preferencias), time() + 86400);
// Recuperando e desserializando
if (isset($_COOKIE['preferencias'])) {
$dados = unserialize($_COOKIE['preferencias']);
echo "Idioma: " . $dados['idioma'];
}
?>
2.2. Removendo e atualizando cookies existentes
<?php
// Removendo cookie (expiração no passado)
setcookie('usuario', '', time() - 3600, '/');
// Atualizando valor
setcookie('preferencia_tema', 'claro', time() + 86400, '/');
?>
2.3. Boas práticas de segurança: SameSite, HttpOnly e Secure flags
<?php
// Cookie seguro com SameSite Strict
setcookie(
'token_sessao',
$token,
[
'expires' => time() + 3600,
'path' => '/',
'domain' => 'meusite.com',
'secure' => true,
'httponly' => true,
'samesite' => 'Strict' // ou 'Lax'
]
);
?>
3. Introdução às Sessions no PHP
3.1. Conceito de sessão e gerenciamento de estado stateless
Sessões no PHP permitem armazenar dados no servidor entre requisições de um mesmo usuário. Diferente dos cookies, os dados da sessão ficam no servidor, e apenas um identificador único (session ID) é enviado ao cliente, normalmente via cookie.
3.2. Iniciando e configurando sessões com session_start()
<?php
// Deve ser chamado antes de qualquer saída HTML
session_start();
// Configurando parâmetros antes de iniciar
ini_set('session.use_strict_mode', 1);
session_set_cookie_params([
'lifetime' => 3600,
'path' => '/',
'domain' => 'meusite.com',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax'
]);
session_start();
?>
3.3. Armazenamento e recuperação de dados via $_SESSION
<?php
session_start();
// Armazenando dados
$_SESSION['usuario_id'] = 42;
$_SESSION['ultimo_acesso'] = time();
// Recuperando dados
if (isset($_SESSION['usuario_id'])) {
echo "Usuário logado: ID " . $_SESSION['usuario_id'];
}
?>
4. Configuração e Personalização de Sessions
4.1. Configurações no php.ini: session.save_path, session.gc_maxlifetime
; php.ini
session.save_path = "/var/lib/php/sessions"
session.gc_maxlifetime = 1440 ; 24 minutos
session.gc_probability = 1
session.gc_divisor = 100
session.cookie_lifetime = 0 ; até o navegador fechar
4.2. Manipuladores de armazenamento: arquivos, banco de dados e Redis
<?php
// Usando Redis para armazenamento de sessão
ini_set('session.save_handler', 'redis');
ini_set('session.save_path', 'tcp://127.0.0.1:6379');
session_start();
?>
4.3. Sessões personalizadas com session_set_save_handler()
<?php
class SessionHandlerPersonalizado implements SessionHandlerInterface {
private $pdo;
public function open($savePath, $sessionName): bool {
$this->pdo = new PDO('mysql:host=localhost;dbname=sessoes', 'user', 'pass');
return true;
}
public function read($sessionId): string {
$stmt = $this->pdo->prepare('SELECT dados FROM sessoes WHERE id = ?');
$stmt->execute([$sessionId]);
return $stmt->fetchColumn() ?: '';
}
public function write($sessionId, $data): bool {
$stmt = $this->pdo->prepare(
'REPLACE INTO sessoes (id, dados, ultimo_acesso) VALUES (?, ?, NOW())'
);
return $stmt->execute([$sessionId, $data]);
}
public function destroy($sessionId): bool {
$stmt = $this->pdo->prepare('DELETE FROM sessoes WHERE id = ?');
return $stmt->execute([$sessionId]);
}
public function close(): bool { return true; }
public function gc($maxlifetime): int {
$stmt = $this->pdo->prepare(
'DELETE FROM sessoes WHERE ultimo_acesso < DATE_SUB(NOW(), INTERVAL ? SECOND)'
);
$stmt->execute([$maxlifetime]);
return $stmt->rowCount();
}
}
session_set_save_handler(new SessionHandlerPersonalizado(), true);
session_start();
?>
5. Ciclo de Vida e Gerenciamento de Sessão
5.1. Regeneração de ID de sessão com session_regenerate_id()
<?php
session_start();
// Após login bem-sucedido, regenerar ID para prevenir fixation
if ($login_sucesso) {
session_regenerate_id(true); // true = deleta sessão antiga
$_SESSION['autenticado'] = true;
}
?>
5.2. Destruição de sessão: session_destroy() e limpeza de cookies
<?php
session_start();
// Limpar dados da sessão
$_SESSION = [];
// Destruir a sessão no servidor
session_destroy();
// Remover o cookie da sessão
setcookie(session_name(), '', time() - 3600, '/');
?>
5.3. Controle de tempo de vida e garbage collection
<?php
// Verificar expiração manual
session_start();
$tempo_maximo = 1800; // 30 minutos
if (isset($_SESSION['ultimo_acesso']) &&
(time() - $_SESSION['ultimo_acesso']) > $tempo_maximo) {
session_destroy();
header('Location: login.php');
exit;
}
$_SESSION['ultimo_acesso'] = time();
?>
6. Segurança em Sessions e Cookies
6.1. Proteção contra session fixation e session hijacking
<?php
session_start();
// Verificar se o ID foi gerado pelo servidor
if (!isset($_SESSION['initiated'])) {
session_regenerate_id(true);
$_SESSION['initiated'] = true;
}
// Validar fingerprint do navegador
if (!isset($_SESSION['fingerprint'])) {
$_SESSION['fingerprint'] = md5($_SERVER['HTTP_USER_AGENT'] . $_SERVER['REMOTE_ADDR']);
} elseif ($_SESSION['fingerprint'] !== md5($_SERVER['HTTP_USER_AGENT'] . $_SERVER['REMOTE_ADDR'])) {
session_destroy();
exit('Sessão inválida');
}
?>
6.2. Validação de User-Agent e IP para mitigar sequestro
<?php
session_start();
$ip_atual = $_SERVER['REMOTE_ADDR'];
$agent_atual = $_SERVER['HTTP_USER_AGENT'];
if (!isset($_SESSION['ip_cliente'])) {
$_SESSION['ip_cliente'] = $ip_atual;
$_SESSION['user_agent'] = $agent_atual;
} elseif ($_SESSION['ip_cliente'] !== $ip_atual ||
$_SESSION['user_agent'] !== $agent_atual) {
// Possível hijacking - invalidar sessão
session_destroy();
header('Location: login.php?erro=seguranca');
exit;
}
?>
6.3. Criptografia de dados sensíveis em sessões e cookies
<?php
// Criptografar dados antes de armazenar na sessão
$dados_sensiveis = ['cartao' => '4111111111111111', 'cvv' => '123'];
$chave = 'minha_chave_secreta_32bytes!';
$iv = openssl_random_pseudo_bytes(16);
$dados_criptografados = openssl_encrypt(
serialize($dados_sensiveis),
'aes-256-cbc',
$chave,
0,
$iv
);
$_SESSION['dados_pagamento'] = base64_encode($iv . $dados_criptografados);
?>
7. Integração entre Sessions e Cookies
7.1. Como o PHP usa cookies para gerenciar IDs de sessão
Por padrão, o PHP utiliza um cookie chamado PHPSESSID para armazenar o ID da sessão no navegador. Esse cookie é do tipo session (expira ao fechar o navegador) e é enviado automaticamente em cada requisição.
7.2. Sessões sem cookies: transmissão via URL (SID)
<?php
ini_set('session.use_cookies', 0);
ini_set('session.use_only_cookies', 0);
ini_set('session.use_trans_sid', 1);
session_start();
$_SESSION['dado'] = 'valor';
// O PHP automaticamente adiciona ?PHPSESSID=X às URLs relativas
echo '<a href="pagina2.php">Próxima página</a>';
?>
7.3. Cache de sessão e impacto no desempenho com cookies
<?php
// Configurar cache para sessões
ini_set('session.cache_limiter', 'private');
ini_set('session.cache_expire', 180); // 3 minutos
session_start();
// Evitar cache de páginas com sessão
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Pragma: no-cache');
?>
8. Casos Práticos e Boas Práticas
8.1. Implementação de login persistente com cookies e sessões
<?php
session_start();
function login($usuario_id, $lembrar = false) {
$_SESSION['usuario_id'] = $usuario_id;
if ($lembrar) {
$token = bin2hex(random_bytes(32));
setcookie('remember_token', $token, time() + 86400 * 30, '/', '', true, true);
// Armazenar hash do token no banco
$hash = password_hash($token, PASSWORD_DEFAULT);
// INSERT INTO tokens (usuario_id, hash) VALUES (?, ?)
}
session_regenerate_id(true);
}
function verificar_login() {
if (isset($_SESSION['usuario_id'])) {
return $_SESSION['usuario_id'];
}
if (isset($_COOKIE['remember_token'])) {
// Verificar token no banco
// SELECT usuario_id FROM tokens WHERE hash = ?
// Se válido, recriar sessão
}
return false;
}
?>
8.2. Carrinho de compras: combinando sessão e cookies
<?php
session_start();
class Carrinho {
public function adicionarItem($produto_id, $quantidade) {
if (!isset($_SESSION['carrinho'])) {
$_SESSION['carrinho'] = [];
}
if (isset($_SESSION['carrinho'][$produto_id])) {
$_SESSION['carrinho'][$produto_id] += $quantidade;
} else {
$_SESSION['carrinho'][$produto_id] = $quantidade;
}
// Cookie para lembrar carrinho por 7 dias
setcookie('carrinho_abandonado', '1', time() + 86400 * 7, '/');
}
public function totalItens() {
return array_sum($_SESSION['carrinho'] ?? []);
}
}
?>
8.3. Debugging: logando sessões e cookies com error_log()
<?php
session_start();
function debug_sessao() {
$info = [
'session_id' => session_id(),
'session_name' => session_name(),
'session_status' => session_status(),
'session_data' => $_SESSION,
'cookie_params' => session_get_cookie_params(),
'cookie_recebido' => $_COOKIE
];
error_log('DEBUG SESSÃO: ' . print_r($info, true));
}
debug_sessao();
?>
Referências
- PHP Manual: Cookies — Documentação oficial sobre criação, leitura e remoção de cookies no PHP
- PHP Manual: Sessions — Documentação completa sobre gerenciamento de sessões no PHP
- PHP The Right Way: Sessions — Guia de boas práticas para uso seguro de sessões em PHP
- OWASP: Session Management Cheat Sheet — Referência de segurança para gerenciamento de sessões
- PHP Security: Session Fixation — Técnicas de proteção contra session fixation no PHP
- Mozilla MDN: Set-Cookie — Documentação técnica sobre o cabeçalho HTTP Set-Cookie e seus atributos