Aislamiento de contexto
¿Qué es?
Context Isolation es una característica que asegura que tanto los scripts preload
como la lógica interna de Electron se ejecuten en un contexto separado al sitio web que carga en un webContents
. Esto es importante para propósitos de seguridad, ya que ayuda a evitar que el sitio web acceda a los internos de Electron o a las poderosas APIs a las que tu script de precarga tiene acceso.
This means that the window
object that your preload script has access to is actually a different object than the website would have access to. Por ejemplo, si establece en su script de precarga window.hello = 'wave'
y el aislamiento de contexto está habilitado, window.hello
será undefined si el sitio web trata de acceder a él.
El aislamiento de contexto está habilitado por defecto desde Electron 12, y es una configuración de seguridad recomendada para todas las aplicaciones.
Migración
Sin aislamiento de contexto, solía proporcionar API desde mi script de precarga utilizando
window.X = apiObject
. ¿Y ahora qué?
Antes: aislamiento de contexto desactivado
Exponer APIs desde su script de precarga a un sitio web cargado en el proceso de renderizado es un caso de uso común. Con el aislamiento contextual deshabilitado, su script de precarga compartiría un objeto global window
común con el renderizador. A continuación, puedes adjuntar propiedades arbitrarias a un script de precarga:
// precargar con contextIsolation deshabilitado
window.myAPI = {
doAThing: () => {}
}
La función doAThing()
podría luego ser usada directamente en el proceso renderizador:
// use la API expuesta en el renderer
window.myAPI.doAThing()
Después: aislamiento de contexto activado
Hay un módulo dedicado en Electron para ayudarle a hacer esto de una manera más sencilla. The contextBridge
module can be used to safely expose APIs from your preload script's isolated context to the context the website is running in. La API también será accesible desde el sitio web en window.myAPI
tal como estaba antes.
// precarga con contextIsolation habilitado
const { contextBridge } = require('electron')
contextBridge.exposeInMainWorld('myAPI', {
doAThing: () => {}
})
// use la API expuesta en el renderer
window.myAPI.doAThing()
Por favor lea la documentación de contextBridge
enlazada arriba para entender completamente sus limitaciones. Por ejemplo, no puede enviar prototipos personalizados o símbolos sobre el puente.
Consideraciones de Seguridad
Sólo activar contextIsolation
y usar contextBridge
no significa automáticamente que todo lo que hagas esté seguro. Por ejemplo, este código es inseguro.
// ❌ Bad code
contextBridge.exposeInMainWorld('myAPI', {
send: ipcRenderer.send
})
Expone directamente una poderosa API sin ningún tipo de filtrado de argumentos. Esto permitiría a cualquier sitio web enviar mensajes IPC arbitrarios, lo cual no deseas que sea posible. La forma correcta de exponer las APIs basadas en IPC sería proporcionar un método por mensaje IPPC.
// ✅ Good code
contextBridge.exposeInMainWorld('myAPI', {
loadPreferences: () => ipcRenderer.invoke('load-prefs')
})
Uso con TypeScript
SI está construyendo su aplicación Electron con TypeScript, querrá añadir tipos a sus APIs expuestas sobre el puente del contexto. El objeto window
del renderizador no tendrá los tipos correctos a menos que extienda los tipos con un declaration file.
Por ejemplo, dado este script preload.ts
:
contextBridge.exposeInMainWorld('electronAPI', {
loadPreferences: () => ipcRenderer.invoke('load-prefs')
})
Puede crear un archivo de declaración interface.d.ts
y aumentar globalmente la interfaz Window
:
export interface IElectronAPI {
loadPreferences: () => Promise<void>,
}
declare global {
interface Window {
electronAPI: IElectronAPI
}
}
Al hacerlo se asegurará que el compilador de TypeScript sepa sobre la propiedad electronAPI
en su objeto global window
al escribir scripts en su proceso renderizador:
window.electronAPI.loadPreferences()