Aller au contenu principal

4. Opening Handshake (Poignée de main d'ouverture)

La poignée de main d'ouverture (Opening Handshake) du protocole WebSocket est conçue pour être compatible avec l'infrastructure HTTP existante. La poignée de main est une requête HTTP Upgrade.

4.1 Client Requirements (Exigences du client)

La requête de poignée de main envoyée par le client doit être une requête HTTP valide au format suivant :

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Extensions: permessage-deflate

Champs d'en-tête obligatoires

Host

  • Contient l'hôte et le numéro de port du serveur
  • Conforme à la spécification HTTP/1.1

Upgrade: websocket

  • doit (MUST) inclure cet en-tête
  • La valeur est "websocket" (insensible à la casse)

Connection: Upgrade

  • doit (MUST) inclure cet en-tête
  • Indique qu'il s'agit d'une requête Upgrade

Sec-WebSocket-Key

  • doit (MUST) inclure cet en-tête
  • Valeur de 16 octets générée aléatoirement, encodée en Base64
  • Utilisée pour vérifier que le serveur comprend le protocole WebSocket

Sec-WebSocket-Version: 13

  • doit (MUST) inclure cet en-tête
  • Le numéro de version actuel est 13

Champs d'en-tête optionnels

Origin

  • Les clients navigateurs doivent (MUST) l'inclure
  • Les clients non-navigateurs peuvent (MAY) l'inclure
  • Utilisé pour la validation de sécurité côté serveur

Sec-WebSocket-Protocol

  • optionnel (OPTIONAL)
  • Spécifie la liste des sous-protocoles supportés par le client
  • Plusieurs valeurs séparées par des virgules

Sec-WebSocket-Extensions

  • optionnel (OPTIONAL)
  • Spécifie les extensions supportées par le client
  • Format : extension-name [; parameter=value]*

4.2 Server-Side Requirements (Exigences côté serveur)

Le serveur doit valider la poignée de main du client et retourner une réponse appropriée.

4.2.1 Reading the Client's Opening Handshake (Lecture de la poignée de main du client)

Le serveur doit (MUST) valider ce qui suit :

  1. Méthode HTTP : Doit être GET
  2. Version HTTP : Au moins HTTP/1.1
  3. En-têtes obligatoires : Host, Upgrade, Connection, Sec-WebSocket-Key, Sec-WebSocket-Version doivent être présents
  4. Sec-WebSocket-Version : Doit être 13 (ou une version supportée par le serveur)

Si la validation échoue, le serveur devrait (SHOULD) retourner un code d'état d'erreur HTTP approprié.

4.2.2 Sending the Server's Opening Handshake (Envoi de la poignée de main du serveur)

Si la validation réussit, le serveur doit (MUST) envoyer une réponse de poignée de main :

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat

Calcul de Sec-WebSocket-Accept

C'est une partie critique de la poignée de main. Le serveur doit calculer comme suit :

  1. Prendre la valeur Sec-WebSocket-Key du client
  2. Concaténer avec la chaîne GUID fixe : 258EAFA5-E914-47DA-95CA-C5AB0DC85B11
  3. Effectuer un hachage SHA-1 sur la chaîne concaténée
  4. Encoder le résultat du hachage en Base64

Exemple d'algorithme (JavaScript) :

const crypto = require('crypto');

function generateAcceptKey(clientKey) {
const GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
const concatenated = clientKey + GUID;
const hash = crypto.createHash('sha1').update(concatenated).digest();
return hash.toString('base64');
}

// Exemple
const clientKey = 'dGhlIHNhbXBsZSBub25jZQ==';
const acceptKey = generateAcceptKey(clientKey);
console.log(acceptKey); // s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

4.3 Collecting Extensions and Subprotocols (Collecte des extensions et sous-protocoles)

Négociation des sous-protocoles

Le client peut lister plusieurs sous-protocoles dans l'en-tête Sec-WebSocket-Protocol :

Sec-WebSocket-Protocol: chat, superchat

Le serveur doit (MUST) sélectionner un (ou aucun) dans la liste du client et le retourner dans la réponse :

Sec-WebSocket-Protocol: chat

Si le serveur ne supporte aucun des sous-protocoles demandés par le client, il peut omettre l'en-tête Sec-WebSocket-Protocol.

Négociation des extensions

La négociation des extensions se fait via l'en-tête Sec-WebSocket-Extensions :

Requête du client :

Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

Réponse du serveur :

Sec-WebSocket-Extensions: permessage-deflate

Le serveur peut accepter, modifier les paramètres ou rejeter les extensions.

4.4 Supporting Multiple Versions (Support de plusieurs versions)

Si le serveur ne supporte pas la version demandée par le client, il devrait (SHOULD) retourner HTTP 426 Upgrade Required et inclure un en-tête Sec-WebSocket-Version listant les versions supportées :

HTTP/1.1 426 Upgrade Required
Sec-WebSocket-Version: 13, 8, 7

Exemples complets de poignée de main

Poignée de main réussie

Client → Serveur :

GET /chat HTTP/1.1
Host: example.com:8000
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Version: 13
Origin: http://example.com

Serveur → Client :

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat

Exemples d'échec de poignée de main

Version non supportée :

HTTP/1.1 426 Upgrade Required
Sec-WebSocket-Version: 13

Origin non acceptée :

HTTP/1.1 403 Forbidden

Considérations de sécurité

  1. Valider l'Origin : Les serveurs devraient valider l'en-tête Origin pour prévenir les attaques cross-site
  2. Utiliser TLS : Utiliser wss:// dans les environnements de production
  3. Valider tous les en-têtes : S'assurer que tous les en-têtes obligatoires sont présents et correctement formatés
  4. Limiter les connexions : Mettre en œuvre une limitation du taux pour prévenir les attaques DoS

Liens de référence