HTML - Messagerie web
Types de messagerie Web
Messagerie par canal
La messagerie par canal permet à deux ou plusieurs contextes de navigation (fenêtres, onglets ou iframes) de communiquer entre eux, même s'ils sont sur des origines différentes. Elle utilise un objet de canal de message pour établir un lien entre les contextes et envoyer des messages entre eux.
La messagerie par canal est utile lorsque vous devez établir un lien direct et bidirectionnel entre les contextes. Par exemple, vous pouvez l'utiliser pour permettre à une fenêtre parente de contrôler un iframe ou pour permettre à deux onglets de partager des données en temps réel.
Conseil: Exemple de messagerie par canal
// Dans le premier contexte de navigation
const channel = new MessageChannel();
const port1 = channel.port1;
const port2 = channel.port2;
// Envoyer port2 au deuxième contexte de navigation
window.postMessage('init', '*', [port2]);
// Écouter les messages sur port1
port1.onmessage = (event) => {
console.log('Message reçu:', event.data);
};
// Dans le deuxième contexte de navigation
window.onmessage = (event) => {
if (event.data === 'init') {
const port2 = event.ports[0];
port2.onmessage = (event) => {
console.log('Message reçu:', event.data);
};
port2.postMessage('Bonjour du deuxième contexte!');
}
};
Messagerie inter-documents
La messagerie inter-documents, également connue sous le nom de postMessage, permet à différents contextes de navigation (fenêtres, onglets ou iframes) de communiquer même s'ils sont sur des origines différentes. Elle utilise la méthode postMessage()
pour envoyer un événement de message au contexte récepteur, qui peut ensuite le gérer à l'aide d'un écouteur d'événements.
La messagerie inter-documents est utile lorsque vous avez besoin de messages unidirectionnels entre les contextes. Par exemple, lorsqu'une fenêtre parente doit demander à un iframe de faire quelque chose ou lorsqu'un onglet doit envoyer des données à un autre onglet.
Conseil: Exemple de messagerie inter-documents
// Dans le contexte d'envoi
const targetWindow = window.parent; // Ou window.opener, ou document.getElementById('myIframe').contentWindow
targetWindow.postMessage('Bonjour de l'expéditeur!', '*');
// Dans le contexte de réception
window.addEventListener('message', (event) => {
if (event.origin === 'http://example.com') {
console.log('Message reçu:', event.data);
}
});
Web Workers
Les Web Workers exécutent des scripts en arrière-plan sans affecter les performances de la page. Ils permettent un traitement lourd dans un thread séparé afin que la page principale reste réactive.
Les Web Workers sont utiles pour les tâches qui prennent du temps comme les calculs complexes et le traitement de données.
Conseil: Exemple de Web Workers
// Dans le script principal
const worker = new Worker('worker.js');
worker.onmessage = (event) => {
console.log('Message reçu du worker:', event.data);
};
worker.postMessage('Bonjour du script principal!');
// Dans worker.js
self.onmessage = (event) => {
console.log('Message reçu dans le worker:', event.data);
self.postMessage('Bonjour du worker!');
};
Considérations de sécurité
Lors de l'utilisation de la messagerie Web, soyez conscient des risques potentiels de sécurité et suivez les meilleures pratiques pour une mise en œuvre sécurisée.
Un risque principal avec la messagerie Web est les attaques par script intersite (XSS). Si vous ne validez pas et ne désinfectez pas les données reçues via les messages, un attaquant pourrait envoyer du code malveillant qui s'exécuterait sur votre page. Cela pourrait lui permettre de voler des données sensibles, d'effectuer des actions au nom de l'utilisateur ou de prendre le contrôle de la page.
Conseil: HTML code example for XSS risk
<p>This is a paragraph with extra spaces.</p>
Lorsqu'un navigateur affiche ce code, il présentera le texte comme suit :
This is a paragraph with extra spaces.
Pour prévenir les attaques XSS, validez et désinfectez toujours les données reçues via les messages. Ne supposez pas que les données sont sûres simplement parce qu'elles proviennent d'une autre fenêtre ou d'un autre worker que vous contrôlez. Traitez toutes les données reçues comme des entrées non fiables et gérez-les en conséquence.
Un autre risque survient lors de l'utilisation de la messagerie Web pour communiquer entre différentes origines. Soyez prudent quant aux origines auxquelles vous faites confiance. Si vous acceptez des messages de n'importe quelle origine sans vérification, un attaquant pourrait envoyer des messages depuis un site malveillant qui tromperaient votre page en lui faisant faire quelque chose qu'elle ne devrait pas. Pour réduire ce risque, vérifiez toujours la propriété origin
de l'événement de message et n'acceptez que les messages provenant d'origines de confiance.
Lors de l'utilisation de la messagerie par canal, sachez que tout contexte recevant un port de message a un accès complet à ce canal. Cela signifie qu'ils peuvent envoyer des messages sur le canal et même le fermer. Donc, ne partagez les ports de message qu'avec des contextes en lesquels vous avez pleinement confiance.
Avec les Web Workers, un risque principal est qu'un worker pourrait se bloquer ou utiliser trop de ressources s'il se retrouve dans une boucle infinie ou essaie d'effectuer trop de travail. Pour éviter cela, utilisez la méthode Worker.terminate()
pour arrêter un worker immédiatement si nécessaire. Structurez votre code de worker pour répondre rapidement aux messages et évitez les tâches de longue durée.
Conseil: Using Worker.terminate() method
var myWorker = new Worker('worker.js');
// Terminate the worker after 5 seconds
setTimeout(function() {
myWorker.terminate();
}, 5000);
Ce code arrête le worker après un temps spécifié pour éviter une surutilisation des ressources.
Voici quelques bonnes pratiques pour une messagerie Web sécurisée :
- Validez et désinfectez toujours les données de message reçues
- N'acceptez que les messages provenant d'origines de confiance
- Soyez prudent lors du partage des ports de message
- Utilisez
Worker.terminate()
pour arrêter les workers qui se comportent mal - Gardez votre code de worker ciblé et réactif
- N'utilisez pas la messagerie Web pour partager des données sensibles sauf si nécessaire
- Utilisez le chiffrement pour les données sensibles si nécessaire
- Testez minutieusement votre code de messagerie Web pour détecter les vulnérabilités potentielles
Exemples pratiques
Application de chat en temps réel
La création d'une application de chat en temps réel montre la puissance de la messagerie Web. Voici un guide pour créer une application de chat basique en utilisant la messagerie par canaux et les Web Workers :
-
Mettez en place la structure HTML pour l'interface de chat, y compris un champ de saisie pour les messages et un conteneur pour afficher l'historique du chat.
-
Créez un nouveau Web Worker pour gérer le traitement et le stockage des messages. Ce worker recevra les messages du script principal, les stockera et renverra l'historique du chat mis à jour lorsqu'il sera demandé.
Conseil: Web Worker pour le chat (chat_worker.js)
let chatHistory = [];
self.onmessage = (event) => {
if (event.data.type === 'newMessage') {
chatHistory.push(event.data.message);
self.postMessage({ type: 'updateHistory', history: chatHistory });
} else if (event.data.type === 'getHistory') {
self.postMessage({ type: 'updateHistory', history: chatHistory });
}
};
- Dans le script principal, créez un nouveau canal de messagerie et envoyez l'un des ports au worker.
Conseil: Script principal (script.js)
const chatWorker = new Worker('chat_worker.js');
const channel = new MessageChannel();
chatWorker.postMessage({ type: 'init', port: channel.port1 }, [channel.port1]);
- Configurez des écouteurs d'événements pour la saisie de messages et la communication par canal. Lorsqu'un nouveau message est saisi, envoyez-le au worker via le canal. Écoutez les mises à jour de l'historique provenant du worker et affichez-les dans l'interface de chat.
Conseil: Écouteurs d'événements et messagerie
const messageInput = document.getElementById('messageInput');
const chatContainer = document.getElementById('chatContainer');
channel.port2.onmessage = (event) => {
if (event.data.type === 'updateHistory') {
const messagesHTML = event.data.history.map(message => `<p>${message}</p>`).join('');
chatContainer.innerHTML = messagesHTML;
}
};
messageInput.addEventListener('keypress', (event) => {
if (event.key === 'Enter') {
const message = messageInput.value;
channel.port2.postMessage({ type: 'newMessage', message });
messageInput.value = '';
}
});
- Lors du chargement de la page, demandez l'historique initial du chat au worker.
Conseil: Demande de l'historique initial du chat
chatWorker.postMessage({ type: 'getHistory' });
Avec ces étapes en place, vous avez une application de chat en temps réel basique qui utilise la messagerie Web pour communiquer entre le script principal et le Web Worker.
Communication inter-domaines
La messagerie Web peut également permettre la communication entre différents domaines en utilisant la messagerie inter-documents :
- Dans la fenêtre parente, créez un iframe avec l'attribut
src
défini sur l'URL de la page avec laquelle vous souhaitez communiquer.
Conseil: Fenêtre parente (parent.html)
<iframe id="myIframe" src="https://example.com/iframe.html"></iframe>
- Dans le script de l'iframe, écoutez les événements de message et traitez-les en fonction du format de données attendu.
Conseil: Script de l'iframe (iframe.js)
window.addEventListener('message', function(event) {
if (event.origin === 'https://example.com' && event.data.type === 'userData') {
console.log('Données utilisateur reçues :', event.data.value);
}
});
- Dans le script de la fenêtre parente, obtenez une référence à la fenêtre de l'iframe et envoyez des messages en utilisant la méthode
postMessage()
.
Conseil: Script de la fenêtre parente (parent.js)
const iframeWindow= document.getElementById('myIframe').contentWindow;
const userData= { name:'John Doe', age :30 };
document.getElementById("myIframe").addEventListener("load", () =>{
iframeWindow.postMessage({type :'userData ', value :userData },'https://example.com ');
});
Avec cette configuration, la fenêtre parente peut envoyer des messages contenant des données utilisateur à l'iframe, et l'iframe peut écouter ces messages et les traiter en conséquence. Cela permet une communication sécurisée entre deux contextes même s'ils sont hébergés sur des domaines différents.
Lors de l'utilisation de la messagerie inter-documents, validez l'origine des messages reçus en vous assurant qu'ils proviennent de sources de confiance, prévenant ainsi les attaques par script intersite (XSS) et d'autres vulnérabilités de sécurité.