Las cookies son fragmentos de información enviados desde el servidor hacia el cliente, almacenados como archivos de texto en el dispositivo del cliente. En cada solicitud subsequente, el navegador incluye estos datos, permitiendo al servidor mantener un registro del estado del cliente.
Propósito de las Cookies
Solucionar el problema de la independencia entre solicitudes HTTP. Debido a que HTTP 1.x es un protocolo sin estado, cada solicitud funciona de manera completamente autónoma. Aunque session también podría resolver esto, nos enfocaremos exclusivamente en las cookies.
Proceso de Solución con Cookies
Una respuesta HTTP que establece una cookie se ve así:
Content-Length: 13
Content-Type: text/plain; charset=utf-8
Date: Sat, 21 Aug 2021 14:18:41 GMT
Set-Cookie: token=abc123
El navegador detecta el encabezado Set-Cookie y guarda esa información. En solicitudes posteriores, incluye la cookie en el encabezado de la petición:
Host: localhost:8080
Cookie: token=abc123
Atributos de las Cookies
Las cookies poseen varios atributos: Nombre, Valor, Dominio, Ruta, Expiración/Max-Age, Tamaño, HTTPOnly, Secure.
Descripción de Atributos
1. Nombre y Valor (Name & Value)
El Nombre identifica la cookie y permite al servidor recuperarla específicamente. El Valor contiene los datos, usualmente utilizado como clave para buscar información en el servidor.
2. Dominio y Ruta (Domain & Path)
Dominio especifica qué dominios pueden acceder a la cookie. Por ejemplo, si se establece en .example.com, tanto sub1.example.com como sub2.example.com podrán leerla.
Ruta delimita las rutas dentro del dominio que pueden acceder. Si path=/admin, solo /admin y sus subdirectorios (/admin/dashboard) podrán leer la cookie.
3. Expiración/Max-Age
Define el tiempo de vida. Si no se especifica, dura hasta que se cierre la sesión del navegador. Con un valor específico, expira automáticamente al alcanzar esa fecha.
4. Tamaño (Size)
Representa la cantidad de caracteres en nombre+valor. Por ejemplo, id=666 tiene Size=5.
5. HTTPOnly
Si es true, la cookie solo viaja en encabezados HTTP, no siendo accesible mdeiante document.cookie desde JavaScript.
Propósito de seguridad: Prevenir ataques XSS que roben cookies.
6. Secure
Indica si la cookie solo puede transmitirse por HTTPS. Es un marcador binario sin valores adicionales.
Cookies en Go
La estructura Cookie en Go:
type Cookie struct {
Name string // Nombre de la cookie
Value string // Valor
Path string // Ruta opcional
Domain string // Dominio opcional
Expires time.Time // Fecha de expiración opcional
RawExpires string // Solo para lectura
// MaxAge=0: sin atributo Max-Age
// MaxAge<0: eliminar cookie ahora (equivalente a Max-Age: 0)
// MaxAge>0: Max-Age presente en segundos
MaxAge int
Secure bool
HttpOnly bool
SameSite SameSite
Raw string
Unparsed []string // Pares atributo-valor sin procesar
}
Implementación en Código
Estableciendo Cookies
package main
import (
"fmt"
"net/http"
"time"
)
func configureRoutes() {
http.HandleFunc("/crear", crearCookie)
http.HandleFunc("/mostrar", mostrarCookies)
}
func crearCookie(w http.ResponseWriter, r *http.Request) {
// Cookie básica
c1 := &http.Cookie{
Name: "sesion_usuario",
Value: "abc123xyz",
Path: "/",
Expires: time.Now().Add(24 * time.Hour),
HttpOnly: true,
Secure: false,
}
http.SetCookie(w, c1)
// Cookie adicional
c2 := &http.Cookie{
Name: "preferencia_idioma",
Value: "es",
MaxAge: 3600, // 1 hora
}
http.SetCookie(w, c2)
fmt.Fprintf(w, "Cookies establecidas correctamente")
}
func mostrarCookies(w http.ResponseWriter, r *http.Request) {
cookies := r.Cookies()
fmt.Fprintf(w, "Cookies recibidas: %d\n", len(cookies))
for _, cookie := range cookies {
fmt.Fprintf(w, "- %s: %s\n", cookie.Name, cookie.Value)
}
}
func main() {
configureRoutes()
fmt.Println("Servidor iniciado en :8080")
http.ListenAndServe(":8080", nil)
}
Leyendo Cookies
Go ofrece dos métodos principales:
// Obtener todas las cookies
cookies := r.Cookies()
// Obtener cookie específica
sesion, err := r.Cookie("sesion_usuario")
if err != nil {
// Cookie no encontrada
fmt.Fprintf(w, "Sesión no iniciada")
} else {
fmt.Fprintf(w, "Usuario: %s", sesion.Value)
}
Aplicaciones Prácticas
Notificaciones de Uso Único
func mostrarNotificacion(w http.ResponseWriter, r *http.Request) {
notificacion, err := r.Cookie("mensaje_temporal")
if err != nil {
fmt.Fprintf(w, "No hay mensajes nuevos")
return
}
// Mostrar mensaje y eliminar cookie
fmt.Fprintf(w, "Mensaje: %s", notificacion.Value)
// Marcar para eliminación
notificacion.MaxAge = -1
http.SetCookie(w, notificacion)
}
Características de las Cookies
Ventajas
- No consumen recursos del servidor (se almacenan en el cliente)
- Permiten configurar reglas de expiración flexibles
Desventajas
- Aumentan el tráfico (se envían en cada petición HTTP)
- Transmisión en texto claro (vulnerable sin HTTPS)
- Limitación de tamaño (~4KB)
- No comparten entre navegadores diferentes
- Vulnerables a ataques XSS si no se usa HttpOnly
Mejores Prácticas de Seguridad
- Configurar HttpOnly=true siempre que sea posible
- Usar Secure=true con HTTPS
- Establecer SameSite appropriately
- Definir Path y Domain específicos
- Implementar expiración adecuada con MaxAge/Expires
- Validar cookies del lado del servidor con datos del cliente
Inspección de Cookies en Chrome
- Navegar a
chrome://settings/siteData - Buscar el dominio específico
- Inspeccionar los atributos de cada cookie
Nota: El atributo "Scripts access" indica si JavaScript puede leer la cookie (HttpOnly=false).