Les cookies
Funcionament de les Cookies en PHP
El procés de creació i ús d'una cookie amb PHP es basa en la comunicació mitjançant capçaleres HTTP:
-
Creació (Servidor a Client): Quan un script PHP vol crear o modificar una cookie, utilitza la funció
setcookie(). Aquesta funció no escriu immediatament la cookie al navegador, sinó que afegeix una capçalera HTTP anomenadaSet-Cookiea la resposta del servidor.-
Restricció Crítica: La capçalera
Set-Cookie(i per tant la funciósetcookie()) ha de ser enviada abans que qualsevol sortida (output) de l'script (HTML, espais en blanc, etc.). Si PHP ja ha començat a enviar el cos de la pàgina, no pot enviar capçaleres addicionals, i la funció fallarà, provocant un error de tipus "Headers already sent".
-
-
Emmagatzematge (Client): El navegador web de l'usuari rep la capçalera
Set-Cookiei desa el parell clau-valor de manera local. -
Transmissió (Client a Servidor): En cada petició posterior que l'usuari faci al domini corresponent, el navegador inclou automàticament la cookie en la capçalera HTTP de la petició, anomenada simplement
Cookie. -
Lectura (Servidor amb PHP): PHP llegeix la capçalera
Cookierebuda i omple automàticament la variable superglobal$_COOKIE. El script pot accedir a les dades de la cookie com si fos un array associatiu ($_COOKIE['nom_cookie']).
Exemple d'Ús amb PHP
Per manipular les cookies utilitzem principalment dues eines en PHP: la funció setcookie() per crear-les i la variable $_COOKIE per llegir-les.
- Establir una Cookie
La sintaxi bàsica de setcookie() és:
// Ha d'estar abans de <html> o echo!
// Cookie de sessió (expira al tancar el navegador)
setcookie("usuari", "JordiCatalà");
// Cookie persistent (expira en 30 dies)
$expiracio = time() + (86400 * 30); // 86400 segons = 1 dia
setcookie("preferencia_idioma", "ca", $expiracio, "/");
// Els paràmetres addicionals (path, secure, httponly) són opcionals i clau per la seguretat.
- Llegir i Eliminar una Cookie
<?php
// Llegir una cookie
if (isset($_COOKIE['preferencia_idioma'])) {
$idioma_seleccionat = $_COOKIE['preferencia_idioma'];
echo "L'usuari prefereix l'idioma: " . $idioma_seleccionat;
} else {
echo "No s'ha trobat cap preferència d'idioma.";
}
// Eliminar una cookie
// Per eliminar-la, es crida setcookie() amb una data d'expiració en el passat.
setcookie("usuari", "", time() - 3600); // El valor i la data d'expiració es mouen cap enrere
Avantatges de les Cookies
| Avantatge | Descripció Detallada |
| Persistència d'Estat | Permeten mantenir la informació d'una petició a l'altra, simulant una "memòria" en HTTP. |
| Empremta Lleugera | Són petits fitxers de text que no requereixen recursos del servidor per emmagatzemar la dada. |
| Identificació d'Usuari | Són essencials per a funcions de "Recorda'm" (autologin) i per a la implementació de sessions (la cookie de sessió només conté l'identificador de la sessió). |
| Personalització | Permeten desar preferències d'usuari (idioma, tema, tipus de lletra) sense haver de passar per una base de dades. |
Inconvenients de les Cookies
| Inconvenient | Descripció Detallada |
| Límit de Mida | La majoria de navegadors limiten la mida a 4 KB per cookie i a unes 20-50 cookies per domini. No són aptes per emmagatzemar grans quantitats de dades. |
| Riscos de Seguretat | Si s'emmagatzema informació sensible (com una contrasenya) sense xifrar, pot ser compromesa fàcilment, ja que es transmeten en cada petició. Això es mitiga usant els atributs Secure i HttpOnly. |
| Control del Client | Les cookies s'emmagatzemen al costat del client, cosa que significa que l'usuari pot esborrar-les, modificar-les o directament deshabilitar-les al seu navegador. |
| Regulació (GDPR/LSSI) | A causa de la seva funció de rastreig, les cookies (especialment les de tercers) estan subjectes a estrictes normatives de privacitat i requereixen el consentiment explícit de l'usuari abans de ser establertes. |
| Retard de Latència | Com que es reenvien amb cada petició HTTP (fins i tot per a imatges o fitxers estàtics), poden afegir un petit overhead de latència, especialment si són moltes i grans. |
La funció setcookie()
Per protocol, setcookie() ha de ser cridada abans que qualsevol output (sortida) es generi a l'script (com ara HTML, echo, print, o fins i tot espais en blanc abans de l'etiqueta <?php).
- Paràmetres de setcookie()
La funció accepta fins a set paràmetres (o vuit a PHP 7.3+ si s'utilitza l'array d'opcions):
| Posició | Nom del Paràmetre | Requerit | Descripció |
| 1 | name |
Sí | El nom de la cookie. Aquest nom s'utilitzarà per accedir a la dada a través de $_COOKIE['name']. |
| 2 | value |
No | El valor de la cookie. La dada que es vol emmagatzemar (ex: un ID d'usuari). Aquest valor es codifica automàticament a URL. |
| 3 | expire |
No | El temps d'expiració de la cookie com a timestamp UNIX. Si s'estableix a 0 (per defecte), la cookie expirarà quan l'usuari tanqui el navegador (és a dir, serà una cookie de sessió). |
| 4 | path |
No | El camí del servidor on la cookie estarà disponible. Utilitzar "/" la fa accessible a tot el domini. El valor per defecte és el directori actual on es crida setcookie(). |
| 5 | domain |
No | El domini pel qual la cookie està disponible (ex: "exemple.cat"). Per fer-la accessible també als subdominis (ex: blog.exemple.cat), s'ha d'anteposar un punt (ex: ".exemple.cat"). |
| 6 | secure |
No | Booleà. Si es posa a true, la cookie només s'enviarà a través de connexions HTTPS segures. És una bona pràctica de seguretat. |
| 7 | httponly |
No | Booleà. Si es posa a true, la cookie serà inaccessible per llenguatges de scripting del costat del client (com JavaScript). Ajuda a mitigar atacs de Cross-Site Scripting (XSS). |
Exemple 1: Cookie de Sessió Bàsica
<?php
// Usuari ha iniciat sessió.
// La cookie expira quan es tanca el navegador (expire = 0 per defecte).
setcookie("session_id", "abc12345def67890", 0, "/");
echo "Cookie de sessió establerta.";
// L'usuari veurà la cookie la propera vegada que carregui una pàgina.
Exemple 2: Cookie Persistent amb Configuració de Seguretat
<?php
// Temps d'expiració: ara + (segons en un dia * 7 dies)
$expiracio_7_dies = time() + (86400 * 7);
$path_total = "/";
$domini = "exemple.cat"; // La cookie és vàlida per a exemple.cat
setcookie(
"tema_preferit", // name
"foscur", // value
$expiracio_7_dies, // expire
$path_total, // path
$domini, // domain
true, // secure (Només HTTPS)
true // httponly (No accessible per JS)
);
echo "Cookie persistent establerta per 7 dies.";
Exemple 3: Eliminar una Cookie
Per eliminar una cookie, s'ha de cridar setcookie() amb el mateix nom, el mateix path i el mateix domain, i establir el temps d'expiració a una data passada.
<?php
// Només cal establir l'expiració en el passat i igualar el path i el domini si es van utilitzar
setcookie("tema_preferit", "", time() - 3600, "/", "exemple.cat");
echo "Cookie 'tema_preferit' eliminada.";
// La cookie desapareixerà del navegador de l'usuari després d'aquesta petició.
- Ús de l'Array d'Opcions (PHP 7.3+)
A partir de PHP 7.3, es pot utilitzar una sintaxi més llegible passant un array d'opcions com a tercer paràmetre, en lloc de passar tots els valors individuals. Això permet incloure opcions avançades com l'atribut SameSite (crític per la seguretat web moderna).
| Clau de l'Array | Equival a Paràmetre |
'expires' |
expire (timestamp) |
'path' |
path |
'domain' |
domain |
'secure' |
secure (booleà) |
'httponly' |
httponly (booleà) |
'samesite' |
Nou. Pot ser 'Strict', 'Lax' o 'None'. |
Exemple 4: Cookie amb SameSite
<?php
$opcions = [
'expires' => time() + 3600, // Expira en 1 hora
'path' => '/',
'domain' => '.aplicacio.com',
'secure' => true,
'httponly' => true,
'samesite' => 'Lax' // Millora la seguretat contra CSRF
];
// setcookie(name, value, array $options)
setcookie('token_remember', 'abcdef123456', $opcions);
echo "Cookie amb opcions de seguretat modernes establerta.";
- El paràmetre samesite (PHP 7.3+)
El paràmetre SameSite és un atribut de seguretat fonamental per a les cookies que va ser introduït per mitigar un tipus de vulnerabilitat web molt comú: els atacs de Falsificació de Peticions en Llocs Creuats (Cross-Site Request Forgery o CSRF).
Aquest paràmetre controla si una cookie ha de ser enviada automàticament pel navegador quan la petició s'origina des d'un lloc web diferent al que va establir la cookie.
Funcionament i Tipus de Valors
L'atribut SameSite es configura en la capçalera Set-Cookie enviada pel servidor i accepta tres valors principals: Lax, Strict i None.
1. SameSite=Lax (Recomanat per Defecte)
Aquest és el mode d'equilibri, i el valor recomanat per la majoria d'aplicacions:
-
Com funciona: La cookie NO s'envia quan la petició es fa des d'un lloc extern (tercer) mitjançant mètodes insegurs com
POST. -
Excepció: La cookie SÍ s'envia si la navegació des del lloc extern es fa a través d'un mètode segur (
GET), com en el cas d'un clic en un enllaç o la càrrega d'una imatge. -
Ús: És ideal per a cookies que mantenen la sessió (com les de PHP, si no s'utilitza
Strict), ja que permet que els usuaris puguin arribar al vostre lloc a través d'enllaços externs sense perdre la sessió immediatament, alhora que ofereix protecció contra CSRF bàsic.
2. SameSite=Strict (Màxima Seguretat)
Aquest mode ofereix la màxima protecció contra atacs CSRF.
-
Com funciona: La cookie MAI s'envia si la petició es fa des d'un context de lloc creuat (cross-site), independentment del mètode HTTP utilitzat.
-
Ús: S'ha d'utilitzar per a cookies que gestionen estats d'alta seguretat o accions molt sensibles (per exemple, les cookies que s'utilitzen per confirmar una operació financera o canvis de contrasenya).
-
Inconvenient: Si un usuari inicia sessió i després fa clic en un enllaç al vostre propi lloc web des d'un correu electrònic o una altra aplicació, la cookie de sessió no s'enviarà, i l'usuari semblarà que no ha iniciat sessió.
3. SameSite=None (Sense Protecció)
Aquest valor inhabilita completament la protecció i permet l'enviament de la cookie en totes les peticions de lloc creuat.
-
Com funciona: La cookie S'envia sempre amb les peticions de lloc creuat.
-
Requeriment: Quan s'utilitza
SameSite=None, la cookie HA D'incloure obligatòriament l'atributSecure(és a dir, només es pot enviar a través de HTTPS). -
Ús: Només s'ha d'utilitzar quan la cookie és estrictament necessària per a la funcionalitat d'un tercer (per exemple, widgets incrustats, píxels de seguiment o serveis publicitaris).
Exemple d'Implementació amb PHP
A partir de PHP 7.3, l'atribut SameSite es configura millor mitjançant l'array d'opcions a la funció setcookie():
<?php
// 1. Cookie amb SameSite=Strict (Alta seguretat)
setcookie('sessio_estricta', 'token123', [
'expires' => time() + 3600,
'path' => '/',
'httponly' => true,
'samesite' => 'Strict'
]);
// 2. Cookie amb SameSite=Lax (Valor recomanat per defecte)
setcookie('preferencia_usuari', 'mode_clar', [
'expires' => time() + (86400 * 30),
'path' => '/',
'httponly' => true,
'samesite' => 'Lax'
]);
// 3. Cookie amb SameSite=None (S'usa per a tercers, requereix 'Secure' = true)
setcookie('widget_tercers', 'data_widget', [
'expires' => time() + 86400,
'path' => '/',
'secure' => true, // OBLIGATORI amb SameSite=None
'samesite' => 'None'
]);
Importància en la Seguretat (CSRF)
Sense l'atribut SameSite, un atacant podria fer que un usuari iniciat en una aplicació (per exemple, un banc) fes clic en un enllaç o carregués una imatge en un lloc web maliciós. Aquest lloc web maliciós podria enviar una petició amagada al banc (per exemple, de transferència de fons).
L'atribut SameSite impedeix aquest comportament en la majoria de casos, ja que instruccions com Lax o Strict fan que la cookie no s'adjunti a la petició iniciada des del lloc maliciós, neutralitzant l'atac.