Protocol HTTP
El protocol HTTP
HTTP va néixer a principis dels anys 90 al CERN, de la mà de Tim Berners-Lee, amb l’objectiu de facilitar l’intercanvi d’informació científica mitjançant documents en format hipertext. La primera versió, HTTP/0.9, era extremadament simple: només permetia la transferència de text pla.
El funcionament d’Internet tal com el coneixem avui no seria possible sense el protocol HTTP (HyperText Transfer Protocol). Aquest protocol defineix com es comuniquen els navegadors (clients) amb els servidors web, establint un llenguatge comú per sol·licitar i transferir pàgines, imatges o aplicacions.
A mesura que el web va créixer, van aparèixer noves versions:
- HTTP/1.0 (1996) → S’introdueixen capçaleres, codis d’estat i tipus de contingut.
- HTTP/1.1 (1997) → Millora la persistència de connexions i introdueix la compressió i cache.
- HTTP/2 (2015) → Optimitza la velocitat amb multiplexació, priorització i binarització.
- HTTP/3 (2022) → Basat en el protocol QUIC sobre UDP, redueix la latència i millora la seguretat.
Actualment, HTTP/2 i HTTP/3 són els estàndards moderns més utilitzats, especialment per aplicacions dinàmiques i serveis en el núvol.
Anatomia d'una URL
Abans d'entrar en el funcionament del protocol, cal saber identificar les parts d'un URL (Uniform Resource Locator), el mecanisme que localitza un recurs a Internet:
https://blog.exemple.cat/articles/dns?ordre=data&filtre=actiu
└─┬──┘ └─┬─┘└───┬────┘└─────┬─────┘└──────────┬───────────┘
protocol subdomini domini path query parameters
- Protocol (
https://): com es transporta la petició. - Subdomini i domini (
blog+exemple.cat): identifiquen el servidor; junts formen el host. - Path (
/articles/dns): el recurs concret dins del servidor. - Query parameters (
?ordre=data&filtre=actiu): paràmetres addicionals, típicament enviats ambGET.
Funcionament
El model d’interacció d’HTTP és client-servidor: el client (normalment un navegador) envia una petició (request) i el servidor respon amb una resposta (response). Cada missatge segueix una estructura ben definida. (Vegeu els rols de client i servidor a la pàgina d'Arquitectures Web.)
Exemple de petició HTTP:
Exemple de resposta HTTP:
Els codis d’estat HTTP indiquen el resultat de la petició:
- 1xx → Informatius
- 2xx → Èxit (ex:
200 OK,201 Created) - 3xx → Redireccions (
301 Moved Permanently) - 4xx → Errors del client (
404 Not Found,403 Forbidden) - 5xx → Errors del servidor (
500 Internal Server Error)
Mètodes HTTP principals
- GET: sol·licita un recurs. Es considera idempotent i segur: s'hauria de poder repetir tantes vegades com es vulgui (refrescar la pàgina, tornar enrere) sense que això modifiqui cap dada al servidor. Els paràmetres viatgen a l'URL, per això queden als marcadors i a l'historial.
- POST: envia dades (típicament d'un formulari) que poden modificar l'estat del servidor. No és idempotent: els navegadors avisen abans de reenviar un POST (per exemple, en refrescar la pàgina de confirmació d'una compra).
- PUT: crea o reemplaça per complet un recurs a l'URL indicada.
- DELETE: elimina el recurs indicat a l'URL.
- HEAD: igual que un GET però el servidor només retorna les capçaleres, sense el cos. S'utilitza per comprovar mida o data de modificació d'un recurs abans de descarregar-lo (per exemple, per decidir si cal actualitzar la cache).
- OPTIONS: pregunta al servidor quins mètodes estan permesos sobre un recurs; és la base del preflight de CORS (vegeu més avall).
- CONNECT / TRACE: menys habituals —
CONNECTestableix túnels (per exemple, per a proxies HTTPS) iTRACEretorna la petició tal com l'ha rebut el servidor; per motius de seguretat sol estar desactivat per defecte.
PUT i DELETE solen estar bloquejats per defecte
La majoria de servidors web deneguen PUT i DELETE en la seva configuració per defecte (responent 405 Method Not Allowed), precisament perquè permetrien modificar o esborrar contingut del servidor sense cap control addicional si no s'habiliten expressament amb l'autenticació i autorització adequades.
AC0375/03/01 — Miniactivitat
RA3 · CA3a
Obre les eines de desenvolupador del navegador (pestanya Network) o Wireshark, navega a un lloc web qualsevol i captura la petició i la resposta HTTP de la pàgina principal. Identifica el mètode utilitzat, el codi d'estat de la resposta i almenys quatre capçaleres (de petició i de resposta), explicant la funció de cadascuna.
Estat i sessió: Cookies, Sessions i JWT
HTTP és, per disseny, un protocol sense estat (stateless): cada petició és independent i el servidor no recorda res de peticions anteriors. Per poder mantenir un inici de sessió, una cistella de la compra o unes preferències, calen mecanismes addicionals: cookies i sessions.
Cookies
Una cookie és un petit fragment de dades que el servidor envia al navegador mitjançant la capçalera Set-Cookie, i que el navegador torna a enviar automàticament en cada petició posterior al mateix origen.
Exemple de resposta que crea una cookie:
HTTP/1.1 200 OK
Set-Cookie: session_id=a3f5c9; Expires=Wed, 09 Jun 2027 10:00:00 GMT; Secure; HttpOnly; SameSite=Strict
Peticions posteriors del navegador al mateix domini:
Atributs d'una cookie
| Atribut | Funció |
|---|---|
Domain / Path |
Defineixen a quins hosts i rutes s'envia la cookie |
Expires / Max-Age |
Data de caducitat; si no se n'indica cap, és una cookie de sessió (s'esborra en tancar el navegador) |
Secure |
La cookie només es transmet sobre HTTPS, mai en text pla |
HttpOnly |
JavaScript no pot llegir la cookie (document.cookie), la qual cosa mitiga el robatori de cookies via XSS |
SameSite |
Controla si la cookie s'envia en peticions cross-site: Strict (mai), Lax (només navegació normal, per defecte als navegadors moderns) o None (sempre, requereix Secure) — la defensa principal contra CSRF |
Compte amb el consentiment
Les cookies no estrictament necessàries (analítica, publicitat, tracking) requereixen consentiment explícit de l'usuari segons el GDPR i la normativa de cookies (ePrivacy). Només les cookies tècnicament imprescindibles (com la de sessió) n'estan exemptes.
Sessions
Guardar tota la informació d'un usuari dins la cookie (nom, preferències, cistella...) faria créixer cada petició HTTP i exposaria dades al client. L'alternativa és una sessió: l'aplicació guarda les dades al servidor i només envia al navegador un identificador curt, l'ID de sessió, perquè el pugui presentar en cada petició posterior — sovint mitjançant una cookie, com les que acabem de veure.
sequenceDiagram
participant N as Navegador
participant S as Servidor
participant BD as Emmagatzematge de sessions
N->>S: POST /login (usuari + contrasenya)
S->>BD: Crea sessió i les seves dades
S-->>N: Set-Cookie: PHPSESSID=k27rda7h8w
N->>S: GET /perfil<br/>Cookie: PHPSESSID=k27rda7h8w
S->>BD: Recupera dades associades a la sessió
S-->>N: Resposta amb el contingut personalitzat
L'ID de sessió normalment viatja dins d'una cookie (cada llenguatge en fa servir un nom per defecte: PHPSESSID a PHP, JSESSIONID a Java/JSP), tot i que també es pot transmetre com a paràmetre d'una URL (?sessid=k27rda7h8w) — una pràctica a evitar, ja que l'ID acaba a l'historial del navegador, als logs del servidor i es pot filtrar més fàcilment.
Segrest de sessió (Session Hijacking)
Si un atacant aconsegueix l'ID de sessió d'una víctima (per exemple, interceptant-lo per XSS o per una xarxa sense xifrar), pot suplantar-la sense conèixer la seva contrasenya. Per això l'ID de sessió s'ha de tractar amb el mateix nivell de protecció que una contrasenya: cookie amb HttpOnly i Secure, regenerar l'ID després de l'inici de sessió, i invalidar-lo al servidor en tancar sessió.
JWT (JSON Web Token)
Les sessions clàssiques obliguen el servidor a guardar l'estat de cada usuari connectat (a memòria, a una base de dades...). Això és un problema quan l'aplicació es reparteix entre molts servidors o microserveis: tots haurien de compartir el mateix emmagatzematge de sessions. El JWT és l'alternativa sense estat (stateless), molt utilitzada en APIs REST i aplicacions SPA: en lloc que el servidor recordi qui ets, el propi testimoni (token) porta la informació necessària, signada perquè no es pugui falsificar.
Un JWT és una cadena de text amb tres parts separades per punts, cadascuna codificada en Base64URL:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0IiwibmFtZSI6IkpvYW4iLCJleHAiOjE3NTAwMDAwMDB9.4f2K9s...
└──────── Header ────────┘└──────────────── Payload ────────────────┘└── Signature ──┘
- Header: l'algorisme de signatura utilitzat (per exemple
HS256oRS256) i el tipus de token (JWT). - Payload: les claims (afirmacions) sobre l'usuari o la sessió — per exemple
sub(identificador de l'usuari),exp(data de caducitat) o camps personalitzats com el rol. - Signature: el resultat de signar el header i el payload amb una clau secreta (HMAC) o una clau privada (RSA/ECDSA). És el que permet al servidor verificar que el token no s'ha manipulat, sense necessitat de consultar cap base de dades.
sequenceDiagram
participant N as Navegador/App
participant API as API
N->>API: POST /login (usuari + contrasenya)
API-->>N: JWT signat (Header.Payload.Signature)
N->>API: GET /dades<br/>Authorization: Bearer <JWT>
API->>API: Verifica la signatura (sense consultar cap BD)
API-->>N: Resposta
El payload NO està xifrat
Un error molt freqüent és pensar que un JWT protegeix la informació que conté. El payload només està codificat en Base64, no xifrat: qualsevol persona pot decodificar-lo i llegir-ne el contingut (proveu-ho a jwt.io). La signatura només garanteix que no s'ha modificat, no que sigui secret. Per tant, mai s'hi ha de guardar informació sensible (contrasenyes, dades personals crítiques).
Comparativa amb les sessions clàssiques:
| Sessió (cookie + ID) | JWT | |
|---|---|---|
| On viu l'estat | Al servidor (o BD de sessions) | Dins del propi token, al client |
| Escalabilitat | Cal compartir l'emmagatzematge entre servidors | Sense estat: qualsevol servidor el pot verificar |
| Revocació immediata | Fàcil (esborrar la sessió al servidor) | Difícil: el token és vàlid fins que caduca, tret que es mantingui una llista de revocació |
| Ús habitual | Aplicacions web tradicionals (sessió al navegador) | APIs REST, SPA, autenticació entre microserveis |
Atac de confusió d'algorisme
Un JWT permet triar l'algorisme de signatura al header, cosa que ha donat lloc a atacs reals: acceptar alg: none (sense signatura) o confondre un algorisme asimètric (RS256, verificat amb clau pública) amb un de simètric (HS256, verificat amb la mateixa clau) permetria a un atacant forjar tokens vàlids. Cal validar sempre l'algorisme esperat al servidor, mai confiar en el que indica el token rebut.
Seguretat entre orígens: SOP i CORS
Un cop una sessió manté l'usuari identificat mitjançant una cookie, cal evitar que qualsevol altra pàgina que l'usuari visiti pugui aprofitar-se'n. D'això s'encarrega la Same-Origin Policy.
Same-Origin Policy (SOP)
La Same-Origin Policy és la regla de seguretat més fonamental del navegador: un script només pot llegir la resposta de peticions fetes al mateix origen des del qual s'ha carregat. Un origen es defineix per la combinació exacta de tres elements: protocol, host i port.
Per exemple, un script carregat des de https://www.exemple.cat:443/ pot llegir recursos de https://www.exemple.cat:443/altra-pagina, però no pot llegir-ne de:
http://www.exemple.cat/— mateix host, però protocol diferenthttps://www.exemple.cat:8443/— mateix host i protocol, però port diferenthttps://api.exemple.net/— domini diferent
La SOP no bloqueja totes les etiquetes HTML
La restricció només s'aplica al codi JavaScript que intenta llegir la resposta. Etiquetes com <img>, <script src="..."> o <iframe> poden seguir carregant recursos d'altres orígens (per això funcionen els CDN de JS o incrustar un mapa extern), encara que el JavaScript de la pàgina no pugui llegir-ne el contingut directament.
Sense la SOP, un script maliciós en qualsevol pàgina podria llegir les respostes d'un altre lloc on l'usuari tingués sessió iniciada (per exemple, el seu banc) simplement fent-hi peticions en segon pla amb les cookies del navegador.
CORS (Cross-Origin Resource Sharing)
El problema és que moltes aplicacions legítimes sí necessiten consumir una API allotjada en un origen diferent (per exemple, app.exemple.cat consumint api.exemple.cat). CORS és el mecanisme que permet al servidor relaxar la SOP de forma explícita i controlada, mitjançant capçaleres de resposta:
Access-Control-Allow-Origin: quins orígens poden llegir la resposta (un domini concret o*)Access-Control-Allow-Methods: quins mètodes HTTP estan permesos des d'altres orígensAccess-Control-Allow-Headers: quines capçaleres personalitzades es poden enviarAccess-Control-Allow-Credentials: si es permeten enviar cookies/credencials en la petició cross-origin
Peticions simples vs. peticions amb preflight
Les peticions "simples" (GET/POST/HEAD amb capçaleres bàsiques) es fan directament. Però si la petició fa servir un mètode com PUT o DELETE, o capçaleres personalitzades, o un Content-Type diferent de application/x-www-form-urlencoded, el navegador primer envia una petició de sondeig (preflight) amb el mètode OPTIONS, per preguntar al servidor si l'operació real serà permesa:
sequenceDiagram
participant B as Navegador
participant A as api.exemple.cat
B->>A: OPTIONS /dades (preflight)<br/>Origin: app.exemple.cat
A-->>B: 204 No Content<br/>Access-Control-Allow-Origin: app.exemple.cat<br/>Access-Control-Allow-Methods: GET, PUT
B->>A: PUT /dades (petició real)<br/>Origin: app.exemple.cat
A-->>B: 200 OK
Error comú de configuració
Configurar Access-Control-Allow-Origin: * juntament amb Access-Control-Allow-Credentials: true és una combinació perillosa i invàlida (els navegadors la rebutgen): si una API necessita acceptar credencials, ha de reflectir un origen concret i validat a Access-Control-Allow-Origin, mai un comodí. Reflectir dinàmicament qualsevol Origin rebut sense validar-lo contra una llista blanca és un error de seguretat habitual que trenca tota la protecció que ofereix CORS.
Millors pràctiques
El checklist de seguretat i les capçaleres de seguretat recomanades s'han mogut a la pàgina de Ciberseguretat dels Serveis Web, juntament amb els atacs més comuns (XSS, CSRF, SQL Injection, Clickjacking, MITM, força bruta, DDoS...).
Optimització de Rendiment
- Habilitar compressió GZIP/Brotli
- Configurar cache adequadament
- Utilitzar CDN per recursos estàtics
- Optimitzar imatges i assets
- Implementar lazy loading
- Utilitzar HTTP/2 o HTTP/3
- Configurar keep-alive connections
Monitoratge Essencial
- Disponibilitat del servei
- Temps de resposta
- Ús de CPU i memòria
- Espai en disc
- Errors HTTP (4xx, 5xx)
- Tràfic de xarxa
- Connexions concurrents
AC0375/03/06 — Miniactivitat
RA3 · CA3h, CA3i
Sobre el servidor web (Apache o IIS) que ja tinguis desplegat, habilita la compressió (GZIP/Brotli) i la cache de recursos estàtics, i mesura amb les eines de desenvolupador del navegador (pestanya Network) la diferència de mida i temps de càrrega abans i després. Revisa també els logs d'accés/error per identificar codis 4xx/5xx.
Referències
Documentació oficial, eines de testatge i vídeos sobre serveis web: consulta la secció Serveis Web a la pàgina d'Annexos · Recursos.