Zum Hauptteil springen

contextBridge

History

Erstellen Sie eine sichere, bidirektionale, synchrone Brücke über isolierte Kontexte.

Process: Renderer

Im Folgenden finden Sie ein Beispiel für das Verfügbarmachen einer API für einen Renderer aus einem isolierten Preload-Skript:

// Preload (Isolierter Kontex)
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld(
'electron',
{
doThing: () => ipcRenderer.send('do-a-thing')
}
)
// Renderer (Hauptkontext)

window.electron.doThing()

Glossar

Hauptkontext

Der "Hauptkontext" ist der JavaScript-Kontext, in dem Ihr Hauptrenderercode ausgeführt wird. Standardmäßig führt die Seite, die Sie in Ihren Renderer laden, Code in diesem Kontext aus.

Isolierter Kontext

Wenn contextIsolation in Ihrem webPreferences aktiviert ist (dies ist das Standardverhalten seit Electron 12.0.0), werden Ihre preload-Skripte in einer "Isolierte Welt" ausgeführt. You can read more about context isolation and what it affects in the security docs.

Methoden

Das contextBridge Modul hat folgende Methoden:

contextBridge.exposeInMainWorld(apiKey, api)

  • apiKey string - Das Schlüsselwort, mit dem die API in window eingefügt werden soll. Die API wird auf window[apiKey] zugänglich sein.
  • api any - Ihre API, weitere Informationen darüber, was diese API sein kann und wie sie funktioniert, finden Sie unten.

contextBridge.exposeInIsolatedWorld(worldId, apiKey, api)

  • worldId Integer - The ID of the world to inject the API into. 0 is the default world, 999 is the world used by Electron's contextIsolation feature. Using 999 would expose the object for preload context. We recommend using 1000+ while creating isolated world.
  • apiKey string - Das Schlüsselwort, mit dem die API in window eingefügt werden soll. Die API wird auf window[apiKey] zugänglich sein.
  • api any - Ihre API, weitere Informationen darüber, was diese API sein kann und wie sie funktioniert, finden Sie unten.

Beispiel

API

Die API, die Sie exposeInMainWorld bereitstellten muss eine Function, string, number, Array, boolean oder ein Objekt sein, dessen keys Strings und Werte eine Function, string, number, Array, boolean sind oder ein anderes verschachteltes Objekt, das dieselben Bedingungen erfüllt.

Function-Werte werden in den Renderkontext proxidiert, und alle anderen Werte werden kopiert und eingefroren. Alle Daten / Primitive, die der API gesendet werden, werden unveränderlich und Aktualisierungen auf beiden Seiten der Bridge führen nicht zu einem Update auf der anderen Seite.

Im Folgenden finden Sie ein Beispiel für eine komplexe API:

const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld(
'electron',
{
doThing: () => ipcRenderer.send('do-a-thing'),
myPromises: [Promise.resolve(), Promise.reject(new Error('whoops'))],
anAsyncFunction: async () => 123,
data: {
myFlags: ['a', 'b', 'c'],
bootTime: 1234
},
nestedAPI: {
evenDeeper: {
youCanDoThisAsMuchAsYouWant: {
fn: () => ({
returnData: 123
})
}
}
}
}
)

An example of exposeInIsolatedWorld is shown below:

const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInIsolatedWorld(
1004,
'electron',
{
doThing: () => ipcRenderer.send('do-a-thing')
}
)
// Renderer (In isolated world id1004)

window.electron.doThing()

API-Funktionen

Function Werte, die Sie durch die contextBridge binden, werden durch Electron proxiiert, um sicherzustellen, dass Kontexte isoliert bleiben. Dies führt zu einigen wichtigen Einschränkungen, die wir unten beschrieben haben.

Parameter / Error / Return Type support

Da Parameter, Fehler und Rückgabewerte kopiert werden, wenn sie über die Bridge gesendet werden, gibt es nur bestimmte Typen, die verwendet werden können. Einfach gesagt, wenn der Typ, den Sie verwenden möchten, serialisiert und in dasselbe Objekt deserialisiert werden kann, funktioniert es. Eine Tabelle mit Typ-Support wurde unten für Vollständigkeit hinzugefügt:

TypKomplexitätParameter SupportReturn Value SupportEinschränkungen
stringSimpleN/A
numberSimpleN/A
booleanSimpleN/A
ObjectComplexObjekte dürfen nur mit "Einfachen" Typen in dieser Tabelle unterstützt werden. Typen müssen in dieser Tabelle unterstützt werden. Änderungen des Prototyps werden gelöscht. Das Senden benutzerdefinierter Klassen kopiert Werte, aber nicht den Prototyp.
ArrayComplexGleiche Einschränkungen wie beim Typ Object
ErrorComplexErrors that are thrown are also copied, this can result in the message and stack trace of the error changing slightly due to being thrown in a different context, and any custom properties on the Error object will be lost
PromiseComplexN/A
FunctionComplexÄnderungen des Prototyps werden gelöscht. Das Senden von Klassen oder Konstruktoren funktioniert nicht.
Cloneable TypesSimpleAnzeigen des verknüpften Dokuments zu Cloneable Types
ElementComplexÄnderungen des Prototyps werden gelöscht. Das Senden von benutzerdefinierten Elementen funktioniert nicht.
BlobComplexN/A
SymbolN/ASymbole können nicht über Kontexte hinweg kopiert werden, sodass sie gelöscht werden

Wenn der Typ, der Ihnen wichtig ist, nicht in der obigen Tabelle aufgeführt ist, wird er wahrscheinlich nicht unterstützt.

Exposing ipcRenderer

Attempting to send the entire ipcRenderer module as an object over the contextBridge will result in an empty object on the receiving side of the bridge. Sending over ipcRenderer in full can let any code send any message, which is a security footgun. To interact through ipcRenderer, provide a safe wrapper like below:

// Preload (Isolated World)
contextBridge.exposeInMainWorld('electron', {
onMyEventName: (callback) => ipcRenderer.on('MyEventName', (e, ...args) => callback(args))
})
// Renderer (Main World)
window.electron.onMyEventName(data => { /* ... */ })

Veröffentlichen von Node-Modulen und Daten

Die contextBridge kann vom Preload-Skript verwendet werden, um Ihrem Renderer Zugriff auf Node-APIs zu gewähren. Die oben gezeigte Tabelle der unterstützten Typen gilt auch für Knoten-APIs, die Sie über contextBridgeverfügbar machen. Bitte beachten Sie, dass viele Node-APIs Zugriff auf lokale Systemressourcen gewähren. Seien Sie sehr vorsichtig, welche Daten und APIs Sie im Rendererkontext, für möglicherweise fremde Ressourcen verfügbar machen.

const { contextBridge } = require('electron')
const crypto = require('node:crypto')
contextBridge.exposeInMainWorld('nodeCrypto', {
sha256sum (data) {
const hash = crypto.createHash('sha256')
hash.update(data)
return hash.digest('hex')
}
})