Almacenamiento en el Navegador

Persistencia de Datos en la Web

Agenda

  • Mecanismos de almacenamiento disponibles
  • Comparación detallada
  • Cuándo usar cada uno
  • Seguridad y mejores prácticas
  • Ejemplos prácticos

localStorage

localStorage: Características

  • Capacidad: 5-10 MB por origen
  • Persistencia: Permanente (hasta limpieza manual)
  • Alcance: Todas las pestañas/ventanas del mismo origen
  • API: Síncrona y simple
  • Tipo de datos: Solo strings

localStorage: Sintaxis Básica

// Guardar
localStorage.setItem('tema', 'oscuro');
localStorage.setItem('usuario', JSON.stringify({ nombre: 'Ana' }));

// Leer
const tema = localStorage.getItem('tema');
const usuario = JSON.parse(localStorage.getItem('usuario'));

// Eliminar
localStorage.removeItem('tema');
localStorage.clear();

localStorage: Casos de Uso

✅ Ideal para:

  • Preferencias de usuario (tema, idioma)
  • Configuraciones de UI
  • Flags de features
  • Estado de onboarding

❌ Evitar para:

  • Tokens de autenticación
  • Datos sensibles
  • Datos con expiración automática

localStorage: Ventajas y Desventajas

Ventajas:

  • ✅ API simple e intuitiva
  • ✅ Persistencia a largo plazo
  • ✅ Compatible con todos los navegadores

Desventajas:

  • ❌ Vulnerable a XSS
  • ❌ Solo almacena strings
  • ❌ API síncrona (bloquea UI)
  • ❌ Capacidad limitada (5-10 MB)

sessionStorage

sessionStorage: Características

  • Capacidad: 5-10 MB por origen
  • Persistencia: Solo durante la sesión de la pestaña
  • Alcance: Solo la pestaña actual
  • API: Idéntica a localStorage
  • Isolamiento: Cada pestaña tiene su propio almacenamiento

sessionStorage: Casos de Uso

✅ Ideal para:

  • Formularios multi-paso
  • Carrito de compras temporal
  • Estado de navegación dentro de sesión
  • Tokens temporales

❌ Evitar para:

  • Datos que deben persistir al cerrar pestaña
  • Información compartida entre ventanas

sessionStorage vs localStorage

Aspecto localStorage sessionStorage
Persistencia Permanente Solo sesión
Alcance Todas las pestañas Una pestaña
Se elimina Manual Al cerrar pestaña
Compartir datos Entre pestañas No

Cookies

Cookies: Características

  • Capacidad: ~4 KB por cookie
  • Persistencia: Configurable (expires/max-age)
  • Alcance: Configurable (domain, path)
  • Enviadas automáticamente: Sí, en cada petición HTTP
  • Acceso: Cliente y servidor

Cookies: Sintaxis Básica

// Cookie simple
document.cookie = "usuario=Ana";

// Con expiración (1 año)
document.cookie = "tema=oscuro; max-age=31536000";

// Con configuración completa
document.cookie = "sessionId=abc123; Secure; HttpOnly; SameSite=Strict; max-age=3600";

// Leer cookies
const cookie = document.cookie;

Cookies: Casos de Uso

✅ Ideal para:

  • Autenticación (Session IDs con HttpOnly)
  • Tokens CSRF
  • Preferencias que necesita el servidor
  • Analytics y tracking

❌ Evitar para:

  • Grandes volúmenes de datos
  • Datos que NO necesita el servidor

Cookies: Ventajas y Desventajas

Ventajas:

  • ✅ Expiración automática configurable
  • ✅ Se envían automáticamente con requests
  • ✅ Atributos de seguridad (HttpOnly, Secure, SameSite)
  • ✅ Soporte universal

Desventajas:

  • ❌ Capacidad muy limitada (~4 KB)
  • ❌ Se envían en TODAS las peticiones (overhead)
  • ❌ API compleja de manejar en JavaScript

IndexedDB

IndexedDB: Características

  • Capacidad: Cientos de MB a GB
  • Persistencia: Permanente
  • API: Asíncrona (eventos/promesas)
  • Tipo de datos: Objetos, arrays, blobs, archivos
  • Estructura: Base de datos NoSQL con índices

IndexedDB: Conceptos Clave

  • Database: Contenedor principal
  • Object Store: Tabla de datos
  • Index: Para búsquedas eficientes
  • Transaction: Operaciones ACID
  • Cursor: Para iterar registros

IndexedDB: Abrir Base de Datos

const request = indexedDB.open("MiApp", 1);

request.onupgradeneeded = (event) => {
  const db = event.target.result;
  const store = db.createObjectStore("usuarios", { 
    keyPath: "id",
    autoIncrement: true 
  });
  store.createIndex("email", "email", { unique: true });
};

request.onsuccess = (event) => {
  const db = event.target.result;
  console.log("DB abierta");
};

IndexedDB: Operaciones CRUD

// Crear
const tx = db.transaction("usuarios", "readwrite");
const store = tx.objectStore("usuarios");
store.add({ nombre: "Ana", email: "ana@example.com" });

// Leer
const request = store.get(1);
request.onsuccess = () => console.log(request.result);

// Actualizar
store.put({ id: 1, nombre: "Ana García" });

// Eliminar
store.delete(1);

IndexedDB: Casos de Uso

✅ Ideal para:

  • Progressive Web Apps (PWA)
  • Almacenamiento offline de datos complejos
  • Caché de grandes conjuntos de datos
  • Aplicaciones que manejan archivos/blobs

❌ Evitar para:

  • Datos simples clave-valor
  • Necesidades de almacenamiento pequeño

IndexedDB: Ventajas y Desventajas

Ventajas:

  • ✅ Gran capacidad (GB)
  • ✅ API asíncrona (no bloquea UI)
  • ✅ Soporta tipos de datos complejos
  • ✅ Transacciones ACID
  • ✅ Índices para búsquedas eficientes

Desventajas:

  • ❌ API compleja y verbosa
  • ❌ Curva de aprendizaje pronunciada
  • ❌ Vulnerable a XSS
  • ❌ Requiere gestión manual de versiones

Matriz de Decisión

¿Cómo elegir el mecanismo correcto?

¿Datos sensibles (tokens, passwords)?
├─ Sí → Cookies (HttpOnly + Secure + SameSite)
└─ No → ¿Cuánto espacio necesitas?
    ├─ < 4 KB → ¿El servidor lo necesita?
    │   ├─ Sí → Cookies
    │   └─ No → localStorage o sessionStorage
    ├─ 4 KB - 10 MB → localStorage o sessionStorage
    └─ > 10 MB → IndexedDB

Matriz de Decisión (cont.)

¿Necesita persistir entre sesiones?
├─ Sí → localStorage, Cookies (con expires), IndexedDB
└─ No → sessionStorage

¿Requiere consultas complejas?
├─ Sí → IndexedDB
└─ No → Otros mecanismos

¿Es data del servidor?
├─ Sí → Cookies (se envía automáticamente)
└─ No → localStorage, sessionStorage, IndexedDB

Mejores Prácticas de Seguridad

Vulnerabilidades Principales

1. Cross-Site Scripting (XSS)

  • Código malicioso inyectado puede leer localStorage/sessionStorage
  • Puede acceder a IndexedDB
  • Mitigación: Validar y sanitizar inputs

2. Cross-Site Request Forgery (CSRF)

  • Uso no autorizado de cookies
  • Mitigación: Atributo SameSite

3. Man-in-the-Middle (MITM)

  • Interceptación de cookies sin Secure
  • Mitigación: HTTPS + atributo Secure

Mejores Prácticas: Cookies

// ❌ MAL - Cookie insegura
document.cookie = "sessionId=abc123";

// ✅ BIEN - Cookie segura (desde servidor)
Set-Cookie: sessionId=abc123; 
  HttpOnly;           // ❌ No accesible desde JS
  Secure;             // ✅ Solo HTTPS
  SameSite=Strict;    // ✅ Protección CSRF
  Max-Age=3600;       // ✅ Expira en 1 hora
  Path=/;

Regla de oro: Los tokens sensibles SIEMPRE van en cookies con HttpOnly desde el servidor, NUNCA en localStorage.

Mejores Prácticas: IndexedDB

// ✅ BIEN - Manejo completo de errores
function guardarDatos(db, data) {
  return new Promise((resolve, reject) => {
    const tx = db.transaction('store', 'readwrite');
    
    tx.onerror = () => reject(tx.error);
    tx.oncomplete = () => resolve();
    
    const store = tx.objectStore('store');
    const request = store.add(data);
    
    request.onerror = () => reject(request.error);
  });
}

// ✅ BIEN - Versionado apropiado
const request = indexedDB.open('MiDB', 2);

request.onupgradeneeded = (event) => {
  const db = event.target.result;
  if (event.oldVersion < 2) {
    // Migraciones de versión 2
  }
};

Ejemplos Prácticos

Puntos Clave

  1. Elige según tus necesidades: No hay una solución única
  2. Seguridad primero: NUNCA datos sensibles sin protección
  3. HTTPS obligatorio: Imprescindible en producción
  4. localStorage ≠ Autenticación: Usa cookies HttpOnly
  5. IndexedDB para datos grandes: Cuando necesites > 10 MB
  6. Valida siempre: Todos los inputs del usuario

Arquitectura Recomendada

Para una aplicación moderna:

Autenticación → Cookies (HttpOnly + Secure + SameSite)
Preferencias → localStorage
Estado temporal → sessionStorage
Datos complejos → IndexedDB

Recursos Útiles

MDN Web Docs:

  • Web Storage API
  • IndexedDB
  • Cookies

Web.dev:

  • Storage for the web
  • Security best practices

Herramientas:

  • Chrome DevTools (Application tab)
  • Firefox Storage Inspector

¿Preguntas?

Recuerda

  • ✅ Seguridad primero
  • ✅ Elige el mecanismo adecuado
  • ✅ Prueba en diferentes navegadores
  • ✅ Maneja errores apropiadamente
  • ✅ Valida y sanitiza inputs
  • ✅ Usa HTTPS en producción

Almacenamiento en el Navegador

By anlijudavid

Almacenamiento en el Navegador

  • 29