Aller au contenu principal

Isolation du contexte

Qu'est-ce que c'est ?

L'isolation du contexte est une fonctionnalité qui garantit l'exécution de vos scripts preload et celle de la logique interne d'Electron dans un contexte différent de celui du site Web que vous chargez dans un webContents. Ceci est important pour des raisons de sécurité car cela empêcher le site Web d'accéder aux fonctionalités d'Electron ou aux API puissantes auxquelles votre script preload a accès.

Cela signifie entre autres que l'objet window auquel votre script de préchargement (preload) a accès est un objet différent de celui auquel le site Web peut accéder. Par exemple, si vous définissez window.hello = 'wave' dans votre script de préchargement et que l’isolation du contexte est activée, window.hello retournera undefined si le site Web tente d’y accéder.

L'isolation du contexte est activée par défaut depuis Electron 12, et c'est un paramètre de sécurité recommandé pour toutes les applications.

Migration

Sans isolation du contexte, j’avais l’habitude de fournir des API à partir de mon script de préchargement à l’aide de window.X = apiObject. Et maintenant, comment dois je faire?

Avant: isolation du contexte désactivée

Un cas d’utilisation courant est d'exposer à un site Web chargé dans un processus de rendu, une API à partir de votre script de préchargement. Lorsque l’isolation contextuelle est désactivée, votre script de préchargement partage un objet window global commun avec le moteur de rendu. Vous pouvez donc dans ce cas attacher n'importe quelle propriété à un script de préchargement:

preload.js
// préchargement avec isolation du contexte désactivé
window.myAPI = {
doAThing: () => {}
}

Dans ce cas la fonction doAThing() peut être utilisée directement dans le processus de rendu :

renderer.js
//utilisation dans le moteur de rendu de l’API exposée 
window.myAPI.doAThing()

Après: isolation du contexte activée

Un module spécifique d'Electron est là pour vous aider à la réalisation de cette isolation. Il s'agit du module contextBridge qui peut être utilisé pour exposer dans le contexte ou le site s'exécute, et ceci en toute sécurité, les API de votre script de préchargement isolé du contexte. L'API restera comme avant, accessible depuis le site web en utilisant window.myAPI.

preload.js
// préchargement avec isolatiçon du contexte activé
const { contextBridge } = require('electron')

contextBridge.exposeInMainWorld('myAPI', {
doAThing: () => {}
})
renderer.js
//utilisation dans le moteur de rendu de l’API exposée 
window.myAPI.doAThing()

Afin de bien comprendre les limites de celui-ci, nous vous conseillons de lire la documentation de contextBridge dont le lien est indiqué ci-dessus. Par exemple, vous ne pouvez pas l'utiliser pour envoyer des prototypes ou des symboles.

Mesures de sécurité

L'activation de contextIsolation et l'utilisation de contextBridge ne signifie pas automatiquement que tout ce que vous faites est sans danger. Par exemple, le code suivant est dangereux.

preload.js
// ❌ Code dangereux
contextBridge.exposeInMainWorld('myAPI', {
send: ipcRenderer.send
})

C'est effectivement dangereux car le code expose directement une API puissante sans aucun fitrage sur les arguments. Cela pourrait permettre à n’importe quel site Web d’envoyer des messages IPC arbitraires et bien sur, ce n'est absolument pas ce que vous souhaitez. La bonne façon d’exposer les API basées sur les IPC est plutôt de fournir une méthode par message IPC.

preload.js
// ✅ Code sécurisé
contextBridge.exposeInMainWorld('myAPI', {
loadPreferences: () => ipcRenderer.invoke('load-prefs')
})

Utilisation avec TypeScript

Si vous créez votre application Electron en utilisant TypeScript, vous aurez probablement besoin d'ajouter des types à vos API exposées via le contextBridege. L’objet window du moteur de rendu n’aura les typages leurs correspondant que si vous étendez les types avec un fichier de déclaration .

Par exemple, avec un tel script preload.ts:

preload.ts
contextBridge.exposeInMainWorld('electronAPI', {
loadPreferences: () => ipcRenderer.invoke('load-prefs')
})

Vous pouvez créer un fichier de déclaration renderer.d.ts et enrichir globalement l’interface Window :

renderer.d.ts
export interface IElectronAPI {
loadPreferences: () => Promise<void>,
}

declare global {
interface Window {
electronAPI: IElectronAPI
}
}

En procédant ainsi vous vous assurez que le compilateur TypeScript aura connaissance de la propriété electronAPI de votre objet global window lors de son utilisation dans les scripts dans votre processus de rendu :

renderer.ts
window.electronAPI.loadPreferences()