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 :
- Méthode HTTP : Doit être GET
- Version HTTP : Au moins HTTP/1.1
- En-têtes obligatoires : Host, Upgrade, Connection, Sec-WebSocket-Key, Sec-WebSocket-Version doivent être présents
- 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 :
- Prendre la valeur
Sec-WebSocket-Keydu client - Concaténer avec la chaîne GUID fixe :
258EAFA5-E914-47DA-95CA-C5AB0DC85B11 - Effectuer un hachage SHA-1 sur la chaîne concaténée
- 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é
- Valider l'Origin : Les serveurs devraient valider l'en-tête
Originpour prévenir les attaques cross-site - Utiliser TLS : Utiliser wss:// dans les environnements de production
- Valider tous les en-têtes : S'assurer que tous les en-têtes obligatoires sont présents et correctement formatés
- Limiter les connexions : Mettre en œuvre une limitation du taux pour prévenir les attaques DoS
Liens de référence
- Chapitre précédent : 3. WebSocket URIs
- Chapitre suivant : 5. Data Framing (Tramage des données)
- Exemple d'implémentation : Calcul de la clé de poignée de main