PHP

PHP

Tutorial PHP: Manejo avanzado de Sesiones y Cookies

PHP: Aprende autenticación de usuarios con sesiones, cómo gestionar login/logout seguros y proteger páginas restringidas en tu aplicación web.

Aprende PHP GRATIS y certifícate

Autenticación de usuarios con sesiones (login, logout)

La autenticación de usuarios es fundamental para controlar el acceso a áreas restringidas de una aplicación web. En PHP, las sesiones permiten mantener la información del usuario a lo largo de varias páginas. A continuación, se presenta cómo implementar un sistema básico de inicio y cierre de sesión utilizando sesiones.

Implementación del formulario de inicio de sesión

Primero, se debe crear un formulario HTML que permita al usuario introducir sus credenciales:

<form method="POST" action="login.php">
    <label for="username">Usuario:</label>
    <input type="text" id="username" name="username" required>
    <label for="password">Contraseña:</label>
    <input type="password" id="password" name="password" required>
    <button type="submit">Iniciar sesión</button>
</form>

Este formulario envía los datos a login.php mediante el método POST, lo cual es más seguro que utilizar GET para enviar información sensible como contraseñas.

Procesamiento de inicio de sesión (login.php)

En login.php, se procesa la autenticación del usuario. Es importante validar y sanitizar los datos de entrada para evitar vulnerabilidades de seguridad:

<?php
session_start();

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // Obtener y sanitizar los datos del formulario
    $username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_SPECIAL_CHARS);
    $password = $_POST['password']; // Se recomienda usar hash en contraseña

    // Validar las credenciales (aquí se debe consultar la base de datos)
    // Ejemplo simplificado con datos estáticos
    $user = 'admin';
    $pass_hash = password_hash('1234', PASSWORD_DEFAULT);

    if ($username === $user && password_verify($password, $pass_hash)) {
        // Autenticación exitosa
        $_SESSION['usuario'] = $username;

        // Regenerar ID de sesión para seguridad
        session_regenerate_id(true);

        header('Location: inicio.php');
        exit;
    } else {
        // Credenciales inválidas
        echo "Nombre de usuario o contraseña incorrectos.\n";
    }
} else {
    // Acceso no permitido
    header('Location: index.php');
    exit;
}

En este código, session_start() inicia una nueva sesión o reanuda la existente. La función password_verify() compara la contraseña ingresada con el hash almacenado. Es esencial utilizar session_regenerate_id(true) después de una autenticación exitosa para prevenir el secuestro de sesión.

Protección de páginas restringidas (inicio.php)

Para restringir el acceso a ciertas páginas, se verifica si la sesión del usuario está activa:

<?php
session_start();

if (!isset($_SESSION['usuario'])) {
    // Usuario no autenticado, redirigir al inicio
    header('Location: index.php');
    exit;
}

// Contenido restringido
echo 'Bienvenido, ' . htmlspecialchars($_SESSION['usuario']) . '!' . "\n";

La función htmlspecialchars() protege contra ataques de Cross-Site Scripting (XSS) al escapar caracteres especiales en la salida.

Cierre de sesión (logout.php)

Para cerrar la sesión y eliminar los datos del usuario, se crea un script logout.php:

<?php
session_start();

// Eliminar todas las variables de sesión
$_SESSION = [];

// Destruir la sesión
session_destroy();

// Eliminar cookie de sesión en el cliente
setcookie(session_name(), '', time() - 42000);

// Redirigir al usuario a la página de inicio
header('Location: index.php');
exit;

Este proceso garantiza que la sesión se elimina tanto en el servidor como en el cliente, forzando al usuario a autenticarse nuevamente para acceder a áreas protegidas.

Consideraciones de seguridad adicionales

Uso de HTTPS: Es vital utilizar HTTPS para cifrar la comunicación y proteger las credenciales durante la transmisión.

Almacenamiento seguro de contraseñas: Nunca almacenar contraseñas en texto plano. Utilizar password_hash() para crear un hash seguro y password_verify() para verificarlo.

Validación y sanitización de entradas: Siempre validar y sanitizar las entradas del usuario para evitar inyecciones SQL y otras vulnerabilidades.

Tiempo de expiración de la sesión: Configurar un tiempo de vida de sesión apropiado para equilibrar la seguridad y la usabilidad.

Implementando estas prácticas, se mejora significativamente la seguridad y robustez del sistema de autenticación en aplicaciones PHP.

Cookies de "recordar usuario" (persistencia de sesión vs. seguridad)

Las cookies de "recordar usuario" permiten que una aplicación web mantenga al usuario autenticado incluso después de cerrar el navegador, proporcionando así una experiencia más conveniente. Sin embargo, implementar esta funcionalidad implica considerar cuidadosamente el equilibrio entre la persistencia de la sesión y la seguridad.

Implementación básica de "Recordar usuario"

Para recordar al usuario, se puede utilizar una cookie que almacene información que permita reanudar la sesión en visitas posteriores. A continuación, se muestra cómo crear una cookie al momento del inicio de sesión:

<?php
// Supongamos que el usuario ha sido autenticado correctamente
session_start();

// Almacenar información en la sesión
$_SESSION['usuario_id'] = $usuario_id;

// Verificar si el usuario seleccionó "Recordar usuario"
if (isset($_POST['recordar_usuario'])) {
    // Generar un token único
    $token = bin2hex(random_bytes(16));

    // Almacenar el token en una cookie con fecha de expiración
    setcookie('recordar_usuario', $token, [
        'expires' => time() + (86400 * 30), // 30 días
        'path' => '/',
        'domain' => 'example.com',
        'secure' => true,       // Solo enviar por HTTPS
        'httponly' => true,     // No accesible desde JavaScript
        'samesite' => 'Strict', // Evita envío en solicitudes de terceros
    ]);

    // Almacenar el token en la base de datos asociado al usuario
    guardarTokenEnBaseDeDatos($usuario_id, $token);
}

En este ejemplo, se genera un token único utilizando random_bytes(), que luego se almacena en una cookie segura. Este token también se guarda en la base de datos asociado al ID del usuario para futuras verificaciones.

Recuperación de la sesión mediante la cookie

Cuando el usuario regresa al sitio, se verifica si la cookie existe y se valida el token:

<?php
session_start();

if (!isset($_SESSION['usuario_id']) && isset($_COOKIE['recordar_usuario'])) {
    $token = $_COOKIE['recordar_usuario'];

    // Obtener el usuario asociado al token
    $usuario_id = obtenerUsuarioPorToken($token);

    if ($usuario_id) {
        // Restaurar la sesión
        $_SESSION['usuario_id'] = $usuario_id;

        // Opcional: regenerar el token y la cookie para mayor seguridad
        $nuevo_token = bin2hex(random_bytes(16));
        actualizarTokenEnBaseDeDatos($usuario_id, $nuevo_token);
        setcookie('recordar_usuario', $nuevo_token, [
            'expires' => time() + (86400 * 30),
            'path' => '/',
            'domain' => 'example.com',
            'secure' => true,
            'httponly' => true,
            'samesite' => 'Strict',
        ]);
    }
}

Aquí se comprueba si la sesión del usuario no está iniciada y si la cookie recordar_usuario está presente. Si el token es válido y coincide con uno almacenado en la base de datos, se reanuda la sesión.

Mejores prácticas de seguridad

Al implementar cookies de "recordar usuario", es crucial seguir prácticas que mitiguen riesgos de seguridad:

  • No almacenar información sensible en la cookie: Nunca guardar contraseñas, nombres de usuario u otros datos confidenciales directamente en la cookie.
  • Utilizar tokens aleatorios y seguros: Generar tokens con funciones criptográficamente seguras como random_bytes() y convertirlos utilizando bin2hex().
  • Establecer flags de seguridad en la cookie:
    • secure: Garantiza que la cookie solo se envíe a través de conexiones HTTPS.
    • httponly: Impide el acceso a la cookie desde JavaScript, reduciendo riesgos de XSS.
    • samesite: Controla cómo se envía la cookie en solicitudes de terceros.

Gestionar la expiración y revocación de tokens: Los tokens deben tener una vida limitada. Al cerrar sesión, se debe eliminar el token tanto del cliente como de la base de datos.

Consideraciones sobre persistencia vs. seguridad

Si bien las cookies de "recordar usuario" mejoran la experiencia del usuario al eliminar la necesidad de iniciar sesión repetidamente, también aumentan la superficie de ataque:

  • Dispositivos compartidos o públicos: Si un usuario selecciona "recordar usuario" en un dispositivo no personal, puede exponer su cuenta a terceros.
  • Robos de cookies: Si un atacante obtiene acceso a la cookie, podría suplantar al usuario. Las banderas secure y httponly ayudan a mitigar este riesgo.
  • Compromiso de tokens: Almacenar los tokens correctamente en la base de datos y revocarlos después de su uso es esencial para mantener la seguridad.

Cierre de sesión y eliminación de cookies

Al cerrar sesión, es importante eliminar la cookie y el token asociado:

<?php
session_start();

// Eliminar variables de sesión y destruir la sesión
$_SESSION = [];
session_destroy();

// Eliminar el token de la base de datos
eliminarTokenDeBaseDeDatos($_SESSION['usuario_id']);

// Eliminar la cookie del cliente
setcookie('recordar_usuario', '', time() - 3600, '/');

// Redirigir al usuario a la página de inicio
header('Location: index.php');
exit;

Al hacerlo, se asegura que el token ya no pueda ser utilizado para autenticarse automáticamente.

Balance entre usabilidad y seguridad

Es fundamental informar a los usuarios sobre los riesgos asociados con la opción de "recordar usuario". Algunas recomendaciones incluyen:

  • Desactivar por defecto la opción y permitir que el usuario la habilite conscientemente.
  • Implementar advertencias en dispositivos no seguros o conexiones no cifradas.
  • Limitar la duración de la persistencia: En lugar de 30 días, considerar períodos más cortos.

Al equilibrar cuidadosamente la comodidad del usuario y las medidas de seguridad, se puede ofrecer una funcionalidad útil sin comprometer la integridad de la aplicación.

Recomendaciones de seguridad (HTTPS, duración, cifrado de datos, etc.)

La seguridad en el manejo de sesiones y cookies es esencial para proteger la información sensible y mantener la integridad de las aplicaciones web desarrolladas en PHP. A continuación, se presentan recomendaciones clave para garantizar una seguridad robusta en estos aspectos.

Una de las primeras medidas es la utilización de HTTPS en todas las comunicaciones entre el cliente y el servidor. El uso de HTTPS asegura que los datos transmitidos estén cifrados, impidiendo que terceros intercepten o manipulen la información. Para forzar el uso de HTTPS, se puede implementar una verificación al inicio del script que redirija al usuario si la conexión no es segura:

<?php
if (empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] !== 'on') {
    $urlSegura = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
    header("Location: $urlSegura");
    exit;
}

Es fundamental configurar adecuadamente las cookies para incrementar su seguridad. Al crear una cookie, se deben establecer parámetros como 'secure' => true, que garantiza que la cookie solo se envíe a través de conexiones HTTPS, y 'httponly' => true, que previene el acceso a la cookie mediante scripts de JavaScript, reduciendo el riesgo de ataques XSS. Además, la opción 'samesite' => 'Strict' o 'Lax' controla el envío de la cookie en solicitudes entre sitios, ayudando a mitigar vulnerabilidades como el Cross-Site Request Forgery (CSRF).

Ejemplo de creación de una cookie segura:

<?php
setcookie('usuario', $valor, [
    'expires' => time() + 3600, // Expira en 1 hora
    'path' => '/',
    'domain' => 'ejemplo.com',
    'secure' => true,
    'httponly' => true,
    'samesite' => 'Strict',
]);

Es recomendable limitar la duración de las sesiones y las cookies para reducir el tiempo en que un token comprometido puede ser utilizado por un atacante. Se puede establecer un tiempo de vida para la sesión y configurar un mecanismo que cierre la sesión después de un periodo de inactividad:

<?php
session_start();

$tiempoInactividad = 600; // 10 minutos
if (isset($_SESSION['ultimoAcceso'])) {
    $tiempoTranscurrido = time() - $_SESSION['ultimoAcceso'];
    if ($tiempoTranscurrido > $tiempoInactividad) {
        session_unset();
        session_destroy();
        header('Location: login.php');
        exit;
    }
}
$_SESSION['ultimoAcceso'] = time();

La regeneración del ID de sesión es otra práctica crucial para mejorar la seguridad. Al utilizar session_regenerate_id(true), se crea un nuevo ID de sesión y se elimina el antiguo, dificultando el secuestro de sesiones. Es aconsejable realizar esta regeneración después de acciones sensibles, como el inicio de sesión o cambios en los privilegios del usuario.

Almacenar datos sensibles en las variables de $_SESSION requiere precaución. Si es necesario guardar información confidencial, es importante cifrarla antes de almacenarla. Se pueden utilizar funciones como openssl_encrypt() y openssl_decrypt() para manejar el cifrado:

<?php
$clave = 'clave_secreta'; // Debe ser gestionada de forma segura
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('AES-256-CBC'));
$datosCifrados = openssl_encrypt($datosSensibles, 'AES-256-CBC', $clave, 0, $iv);
$_SESSION['datos'] = $datosCifrados;
$_SESSION['iv'] = $iv;

Es esencial también establecer políticas de seguridad a nivel de servidor y en la configuración de PHP. Parámetros como session.cookie_secure, session.cookie_httponly y session.cookie_samesite deben estar correctamente configurados en php.ini o mediante session_set_cookie_params():

<?php
session_set_cookie_params([
    'lifetime' => 0,
    'path' => '/',
    'domain' => 'ejemplo.com',
    'secure' => true,
    'httponly' => true,
    'samesite' => 'Strict',
]);
session_start();

La validación y sanitización constante de todos los datos recibidos del usuario es una medida indispensable para prevenir ataques como la inyección de código y comandos. Siempre se deben utilizar funciones como filter_input() o filter_var() para validar las entradas.

Para protegerse contra ataques de Cross-Site Scripting (XSS), es importante escapar correctamente las salidas que incluyen datos proporcionados por el usuario. La función htmlspecialchars() es útil para este propósito:

<?php
echo 'Bienvenido, ' . htmlspecialchars($nombreUsuario, ENT_QUOTES, 'UTF-8') . '!';

Implementar mecanismos que limiten los intentos de autenticación fallidos ayuda a prevenir ataques de fuerza bruta. Se pueden contar los intentos y bloquear temporalmente el acceso después de un número determinado de errores.

El uso de herramientas de registro y monitoreo es vital para detectar actividades sospechosas. Registrar eventos importantes y analizar los logs de forma regular permite identificar y responder rápidamente ante posibles incidentes de seguridad.

Mantener el entorno actualizado es otra recomendación clave. Se deben aplicar las actualizaciones y parches de seguridad tanto de PHP como de todas las bibliotecas y frameworks utilizados. Estar informado sobre las vulnerabilidades conocidas y adoptar prácticas de programación segura contribuye a reducir los riesgos.

Por último, deshabilitar funciones innecesarias y potencialmente peligrosas en la configuración de PHP aumenta la seguridad del entorno. Ajustes como disable_functions en php.ini, y desactivar la exposición de la versión de PHP con expose_php = Off, ayudan a minimizar la información disponible para un atacante.

Seguir estas recomendaciones fortalece la seguridad en el manejo de sesiones y cookies en PHP, protegiendo la información de los usuarios y garantizando la confianza en la aplicación.

Para seguir leyendo hazte Plus

¿Ya eres Plus? Accede a la app

20 % DE DESCUENTO

Plan mensual

19.00 /mes

15.20 € /mes

Precio normal mensual: 19 €
58 % DE DESCUENTO

Plan anual

10.00 /mes

8.00 € /mes

Ahorras 132 € al año
Precio normal anual: 120 €
Aprende PHP GRATIS online

Todas las lecciones de PHP

Accede a todas las lecciones de PHP y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A Php

PHP

Introducción Y Entorno

Instalación Y Primer Programa De Php

PHP

Introducción Y Entorno

Tipos De Datos, Variables Y Constantes

PHP

Sintaxis

Operadores Y Expresiones

PHP

Sintaxis

Estructuras De Control

PHP

Sintaxis

Funciones Y Llamada De Funciones

PHP

Sintaxis

Cadenas De Texto Y Manipulación

PHP

Sintaxis

Manejo De Números

PHP

Sintaxis

Manejo De Fechas Y Tiempo

PHP

Sintaxis

Manejo De Arrays

PHP

Sintaxis

Introducción A La Poo En Php

PHP

Programación Orientada A Objetos

Clases Y Objetos

PHP

Programación Orientada A Objetos

Constructores Y Destructores

PHP

Programación Orientada A Objetos

Herencia

PHP

Programación Orientada A Objetos

Encapsulación

PHP

Programación Orientada A Objetos

Polimorfismo

PHP

Programación Orientada A Objetos

Interfaces

PHP

Programación Orientada A Objetos

Traits

PHP

Programación Orientada A Objetos

Namespaces

PHP

Programación Orientada A Objetos

Autoloading De Clases

PHP

Programación Orientada A Objetos

Manejo De Errores Y Excepciones

PHP

Programación Orientada A Objetos

Manejo De Archivos

PHP

Programación Orientada A Objetos

Patrones De Diseño

PHP

Programación Orientada A Objetos

Introducción A Los Formularios En Php

PHP

Formularios

Procesamiento De Datos De Formularios

PHP

Formularios

Manejo De Archivos En Formularios

PHP

Formularios

Redirecciones Y Retroalimentación Al Usuario

PHP

Formularios

Formularios Dinámicos Y Separación De Lógica

PHP

Formularios

Introducción A La Persistencia En Php

PHP

Persistencia

Conexión A Bases De Datos

PHP

Persistencia

Consultas Y Operaciones Crud

PHP

Persistencia

Gestión De Transacciones

PHP

Persistencia

Manejo De Errores Y Excepciones En Base De Datos

PHP

Persistencia

Patrones De Acceso A Datos

PHP

Persistencia

Concepto De Sesiones En Php

PHP

Sesiones Y Cookies

Configuración De Sesiones

PHP

Sesiones Y Cookies

Cookies

PHP

Sesiones Y Cookies

Manejo Avanzado De Sesiones Y Cookies

PHP

Sesiones Y Cookies

Principales Vulnerabilidades En Php

PHP

Seguridad

Seguridad En Formularios Y Entrada De Datos

PHP

Seguridad

Protección Frente A Inyección Sql

PHP

Seguridad

Gestión De Contraseñas Y Cifrado

PHP

Seguridad

Seguridad En Sesiones Y Cookies

PHP

Seguridad

Configuraciones De Php Para Seguridad

PHP

Seguridad

Introducción Al Testing En Php

PHP

Testing

Phpunit

PHP

Testing

Cobertura De Código En Testing

PHP

Testing

Test Doubles (Mocks, Stubs, Fakes, Spies)

PHP

Testing

Pruebas De Integración Y Funcionales

PHP

Testing

Accede GRATIS a PHP y certifícate

En esta lección

Objetivos de aprendizaje de esta lección

  • Crear formularios de login seguros usando HTML.
  • Implementar autenticación vía sesiones en PHP.
  • Usar password_hash y password_verify para las contraseñas.
  • Proteger páginas restringidas mediante control de sesiones.
  • Implementar cierre seguro de sesión.
  • Explorar cookies de "recordar usuario" y riesgos asociados.