Skip to content

10. Manejo de Sesiones y Cookies

En aplicaciones web, mantener el estado entre diferentes peticiones HTTP es un desafío debido a la naturaleza sin estado del protocolo HTTP. PHP ofrece dos mecanismos principales para resolver este problema: sesiones y cookies. Estos mecanismos permiten almacenar información del usuario entre diferentes páginas y visitas al sitio web.

Las sesiones permiten almacenar datos del usuario en el servidor durante un período de tiempo limitado. Cada usuario recibe un identificador único de sesión (generalmente almacenado en una cookie) que se utiliza para acceder a sus datos de sesión almacenados en el servidor.

PHP proporciona la variable superglobal $_SESSION para acceder y manipular los datos de sesión. Esta variable es un array asociativo que contiene todas las variables de sesión disponibles para el script actual.

Antes de poder utilizar variables de sesión, debes iniciar la sesión con la función session_start(). Esta función debe ser llamada antes de cualquier salida al navegador.

<?php
// Iniciar sesión (debe ser lo primero antes de cualquier salida HTML)
session_start();
// Ahora podemos trabajar con la variable $_SESSION
$_SESSION['usuario'] = 'juan_perez';
$_SESSION['nivel_acceso'] = 'administrador';
$_SESSION['ultimo_acceso'] = time();
?>
<!DOCTYPE html>
<html>
<head>
<title>Ejemplo de Sesión</title>
</head>
<body>
<h1>Sesión iniciada</h1>
<p>Bienvenido, <?php echo $_SESSION['usuario']; ?>!</p>
</body>
</html>

10.1.4 Comprobar si una sesión está activa

Section titled “10.1.4 Comprobar si una sesión está activa”

Puedes verificar si una sesión ya está iniciada utilizando la función session_status():

<?php
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
// Ahora es seguro trabajar con $_SESSION
?>

O comprobar si existe una variable específica en la sesión:

<?php
session_start();
// Comprobar si el usuario ha iniciado sesión
if (isset($_SESSION['usuario'])) {
echo "Bienvenido de nuevo, " . $_SESSION['usuario'];
} else {
echo "Por favor, inicia sesión";
}
?>

Puedes eliminar variables específicas de la sesión o destruir completamente la sesión:

<?php
session_start();
// Eliminar una variable específica de la sesión
unset($_SESSION['ultimo_acceso']);
// Eliminar todas las variables de sesión pero mantener la sesión activa
$_SESSION = array();
// Destruir completamente la sesión
session_destroy();
?>

10.1.6 Implementación de inicio y cierre de sesión

Section titled “10.1.6 Implementación de inicio y cierre de sesión”

A continuación se muestra un ejemplo completo de implementación de inicio y cierre de sesión:

<?php
session_start();
// Verificar si el usuario ya ha iniciado sesión
if (isset($_SESSION['usuario_id'])) {
// Redirigir a la página principal si ya está autenticado
header("Location: dashboard.php");
exit;
}
$error = "";
// Procesar el formulario cuando se envía
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// En un caso real, estos valores vendrían de una base de datos
$usuario_correcto = "admin";
$password_correcto = "password123";
// Obtener datos del formulario
$usuario = $_POST['usuario'] ?? '';
$password = $_POST['password'] ?? '';
// Validar credenciales
if ($usuario === $usuario_correcto && $password === $password_correcto) {
// Credenciales correctas, iniciar sesión
$_SESSION['usuario_id'] = 1;
$_SESSION['usuario_nombre'] = $usuario;
$_SESSION['tiempo_inicio'] = time();
// Recordar usuario si se seleccionó la casilla
if (isset($_POST['recordar']) && $_POST['recordar'] == 1) {
// Crear cookie que dura 30 días
setcookie('usuario_recordado', $usuario, time() + (86400 * 30), "/");
}
// Redirigir al panel de control
header("Location: dashboard.php");
exit;
} else {
$error = "Usuario o contraseña incorrectos";
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Iniciar Sesión</title>
<style>
body { font-family: Arial, sans-serif; max-width: 400px; margin: 0 auto; padding: 20px; }
.error { color: red; margin-bottom: 15px; }
.form-group { margin-bottom: 15px; }
label { display: block; margin-bottom: 5px; }
input[type="text"], input[type="password"] { width: 100%; padding: 8px; }
button { padding: 10px 15px; background-color: #4CAF50; color: white; border: none; cursor: pointer; }
</style>
</head>
<body>
<h1>Iniciar Sesión</h1>
<?php if ($error): ?>
<div class="error"><?php echo $error; ?></div>
<?php endif; ?>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
<div class="form-group">
<label for="usuario">Usuario:</label>
<input type="text" id="usuario" name="usuario" value="<?php echo isset($_COOKIE['usuario_recordado']) ? $_COOKIE['usuario_recordado'] : ''; ?>" required>
</div>
<div class="form-group">
<label for="password">Contraseña:</label>
<input type="password" id="password" name="password" required>
</div>
<div class="form-group">
<label>
<input type="checkbox" name="recordar" value="1" <?php echo isset($_COOKIE['usuario_recordado']) ? 'checked' : ''; ?>> Recordar usuario
</label>
</div>
<button type="submit">Iniciar Sesión</button>
</form>
</body>
</html>

PHP ofrece varias opciones para configurar el comportamiento de las sesiones:

<?php
// Configurar opciones de sesión antes de iniciarla
ini_set('session.gc_maxlifetime', 3600); // Duración de la sesión en segundos (1 hora)
ini_set('session.cookie_lifetime', 3600); // Duración de la cookie de sesión
ini_set('session.use_strict_mode', 1); // Modo estricto para mayor seguridad
ini_set('session.cookie_httponly', 1); // Evita acceso a la cookie desde JavaScript
ini_set('session.cookie_secure', 1); // Solo enviar cookie por HTTPS
ini_set('session.cookie_samesite', 'Lax'); // Protección contra CSRF
// Iniciar la sesión con las configuraciones aplicadas
session_start();
?>

También puedes configurar estas opciones en el archivo php.ini o usando session_set_cookie_params() antes de session_start().

Las cookies son pequeños archivos de texto que se almacenan en el navegador del usuario. A diferencia de las sesiones, las cookies se guardan en el lado del cliente (navegador) y no en el servidor.

PHP proporciona la variable superglobal $_COOKIE para acceder a las cookies enviadas por el navegador del usuario. Esta variable es un array asociativo que contiene todas las cookies disponibles para el script actual.

Para crear una cookie, se utiliza la función setcookie():

<?php
// Sintaxis básica: setcookie(nombre, valor, tiempo_expiracion, ruta, dominio, seguro, httponly)
// Crear una cookie que expira en 30 días
setcookie('usuario', 'juan_perez', time() + (86400 * 30), "/");
// Crear una cookie que expira al cerrar el navegador (cookie de sesión)
setcookie('preferencia_tema', 'oscuro', 0, "/");
// Crear una cookie segura (solo se envía por HTTPS)
setcookie('token', 'abc123', time() + 3600, "/", "", true, true);
?>

Para leer el valor de una cookie, simplemente accede a la variable superglobal $_COOKIE:

<?php
// Verificar si existe una cookie
if (isset($_COOKIE['usuario'])) {
echo "Bienvenido de nuevo, " . htmlspecialchars($_COOKIE['usuario']);
} else {
echo "Bienvenido, visitante";
}
// Acceder a una cookie con un valor predeterminado si no existe
$tema = $_COOKIE['preferencia_tema'] ?? 'claro';
echo "Tema actual: $tema";
?>

Para modificar una cookie existente, simplemente crea una nueva cookie con el mismo nombre:

<?php
// Modificar una cookie existente
setcookie('preferencia_tema', 'claro', time() + (86400 * 30), "/");
?>

Para eliminar una cookie, establece su tiempo de expiración en el pasado:

<?php
// Eliminar una cookie
setcookie('usuario', '', time() - 3600, "/");
?>

10.2.7 Implementación de “Recordar usuario”

Section titled “10.2.7 Implementación de “Recordar usuario””

A continuación se muestra un ejemplo de cómo implementar la funcionalidad “Recordar usuario” utilizando cookies:

<?php
session_start();
// Verificar si hay una cookie de "recordar usuario"
if (!isset($_SESSION['usuario_id']) && isset($_COOKIE['auth_token'])) {
// En un caso real, verificaríamos este token en la base de datos
$token = $_COOKIE['auth_token'];
$usuario_id = verificarToken($token); // Función hipotética
if ($usuario_id) {
// Token válido, iniciar sesión automáticamente
$_SESSION['usuario_id'] = $usuario_id;
$_SESSION['usuario_nombre'] = obtenerNombreUsuario($usuario_id); // Función hipotética
$_SESSION['tiempo_inicio'] = time();
}
}
// Función para crear un token de autenticación
function crearTokenRecordar($usuario_id) {
// En un caso real, generaríamos un token único y lo almacenaríamos en la base de datos
$token = bin2hex(random_bytes(32)); // Genera un token aleatorio seguro
// Almacenar el token en una cookie que dura 30 días
setcookie('auth_token', $token, time() + (86400 * 30), "/", "", true, true);
// Guardar el token en la base de datos junto con el ID de usuario
// guardarTokenEnBaseDeDatos($usuario_id, $token); // Función hipotética
return $token;
}
// Función para eliminar el token de "recordar usuario"
function eliminarTokenRecordar() {
if (isset($_COOKIE['auth_token'])) {
// Eliminar el token de la base de datos
// eliminarTokenDeBaseDeDatos($_COOKIE['auth_token']); // Función hipotética
// Eliminar la cookie
setcookie('auth_token', '', time() - 3600, "/");
}
}
?>

Las cookies pueden ser vulnerables a varios tipos de ataques. Aquí hay algunas prácticas recomendadas para mejorar la seguridad:

ParámetroDescripciónRecomendación
httponlyEvita que la cookie sea accesible mediante JavaScriptEstablecer a true para cookies sensibles
secureLa cookie solo se envía a través de conexiones HTTPSEstablecer a true en sitios con HTTPS
samesiteControla cuándo se envían las cookies en solicitudes entre sitiosUsar ‘Strict’ o ‘Lax’ para prevenir CSRF
pathRuta en el servidor donde la cookie estará disponibleLimitar al mínimo necesario, no usar ’/’ si no es necesario
domainDominio para el que la cookie es válidaEspecificar solo si es necesario compartir entre subdominios
<?php
// Ejemplo de cookie segura
setcookie(
'token_seguro', // Nombre
'valor_encriptado_aqui', // Valor (idealmente encriptado)
time() + 3600, // Expiración (1 hora)
'/app/', // Ruta (restringida a /app/)
'ejemplo.com', // Dominio
true, // Secure (solo HTTPS)
true // HttpOnly (inaccesible por JavaScript)
);
// Para PHP 7.3+ puedes usar el parámetro adicional para samesite
$opciones = [
'expires' => time() + 3600,
'path' => '/app/',
'domain' => 'ejemplo.com',
'secure' => true,
'httponly' => true,
'samesite' => 'Strict' // 'None', 'Lax', o 'Strict'
];
setcookie('token_seguro', 'valor_encriptado_aqui', $opciones);
?>

10.3 Comparación entre Sesiones y Cookies

Section titled “10.3 Comparación entre Sesiones y Cookies”
CaracterísticaSesionesCookies
AlmacenamientoServidorCliente (navegador)
SeguridadMayor (datos sensibles en servidor)Menor (datos expuestos al cliente)
CapacidadLimitada por configuración del servidorLimitada (~4KB por cookie)
DuraciónTemporal (hasta cierre de navegador o timeout)Configurable (temporal o persistente)
DependenciaRequiere cookie o URL para ID de sesiónNo requiere soporte adicional
Uso típicoDatos de autenticación, carritos de compraPreferencias, seguimiento, recordar usuario
  1. Regenerar ID de sesión: Regenera el ID de sesión después de eventos importantes como inicio de sesión o cambio de privilegios.
<?php
session_start();
// Después de una autenticación exitosa
if ($autenticacion_exitosa) {
// Regenerar ID de sesión para prevenir ataques de fijación de sesión
session_regenerate_id(true);
$_SESSION['usuario_id'] = $usuario_id;
// Otros datos de sesión...
}
?>
  1. Validar datos de sesión: Siempre valida los datos almacenados en la sesión antes de usarlos.

  2. Establecer tiempo de expiración: Implementa un mecanismo de timeout para sesiones inactivas.

  3. Usar HTTPS: Configura las cookies de sesión para que solo se transmitan por HTTPS.

  1. No almacenar datos sensibles en cookies: Las cookies son visibles para el usuario y pueden ser manipuladas.

  2. Encriptar datos sensibles: Si necesitas almacenar datos sensibles, encriptalos antes.

<?php
// Encriptar datos antes de almacenarlos en una cookie
$datos_sensibles = "información_confidencial";
$clave_encriptacion = "clave_secreta_muy_larga_y_compleja"; // En producción, usar una clave segura
// Método simple (para datos no críticos)
$datos_encriptados = base64_encode(openssl_encrypt(
$datos_sensibles,
'AES-256-CBC',
$clave_encriptacion,
0,
substr(md5($clave_encriptacion), 0, 16)
));
setcookie('datos', $datos_encriptados, time() + 3600, "/", "", true, true);
// Para desencriptar
if (isset($_COOKIE['datos'])) {
$datos_desencriptados = openssl_decrypt(
base64_decode($_COOKIE['datos']),
'AES-256-CBC',
$clave_encriptacion,
0,
substr(md5($clave_encriptacion), 0, 16)
);
echo "Datos desencriptados: $datos_desencriptados";
}
?>

Implementa un manejo adecuado de errores para situaciones como sesiones expiradas o cookies bloqueadas:

<?php
// Verificar si las cookies están habilitadas
setcookie('test_cookie', '1', 0, '/');
if (isset($_COOKIE['test_cookie'])) {
echo "Las cookies están habilitadas";
} else {
echo "Las cookies están deshabilitadas. Esta aplicación requiere cookies para funcionar correctamente.";
}
// Manejar sesión expirada
session_start();
if (isset($_SESSION['tiempo_ultimo_acceso'])) {
$inactividad = 1800; // 30 minutos
if (time() - $_SESSION['tiempo_ultimo_acceso'] > $inactividad) {
// La sesión ha expirado
session_unset();
session_destroy();
// Redirigir con mensaje
header("Location: login.php?expirado=1");
exit;
}
}
// Actualizar tiempo de último acceso
$_SESSION['tiempo_ultimo_acceso'] = time();
?>

El manejo adecuado de sesiones y cookies es fundamental para desarrollar aplicaciones web seguras y con buena experiencia de usuario. Las sesiones son ideales para almacenar datos sensibles y de autenticación en el servidor, mientras que las cookies son útiles para almacenar preferencias de usuario y facilitar funcionalidades como “recordarme” entre visitas.

Al implementar estos mecanismos, siempre prioriza la seguridad siguiendo las mejores prácticas y considerando las implicaciones de privacidad para los usuarios de tu aplicación.

🐝