问题描述
我正在制作一个需要访问文件系统 (fs) 模块的应用程序,但是即使启用了 nodeIntegration
,渲染器也会给我这个错误:
I'm making an application which I need to give access to the file system (fs) module, however even with nodeIntegration
enabled the renderer gives me this error:
Uncaught ReferenceError: require is not defined
我能找到的所有类似问题都有一个解决方案,说他们需要打开 nodeIntegration
,但是我已经启用了它.
All similar problems I could find had a solution that said they needed to turn nodeIntegration
on, however I already have it enabled.
这是我的 main.js:
This is my main.js:
const electron = require('electron');
const {app, BrowserWindow} = electron;
let win;
app.on('ready', () => {
var { width, height } = electron.screen.getPrimaryDisplay().workAreaSize;
width = 1600;
height = 900;
win = new BrowserWindow({'minHeight': 850, 'minWidth': 1600, width, height, webPreferences: {
contextIsolation: true,
webSecurity: true,
nodeIntegration: true
}});
win.setMenu(null);
win.loadFile('index.html');
win.webContents.openDevTools()
});
我的 index.js,在 index.html 中链接为 <script src="index.js"></script>
目前只有 require("fs");
在里面,我已经注释掉了所有其他的东西.
My index.js, linked in index.html as <script src="index.js"></script>
currently only has require("fs");
in it, I've commented out all the other stuff.
我不知道为什么即使启用了 nodeIntegration
,require 仍然不起作用.
I don't know why require still doesn't work even though nodeIntegration
is enabled.
推荐答案
当你禁用了 nodeIntegration
但没有使用 contextIsolation
时,你可以使用预加载脚本在全局对象上公开它的安全版本.(注意:您不应该将整个 fs
模块暴露给远程页面!)
When you have nodeIntegration
disabled but aren't using contextIsolation
, you could use a preload script to expose a safe version of it on the global object. (Note: you shouldn't expose the entire fs
module to a remote page!)
这是一个以这种方式使用预加载脚本的示例:
Here's an example of using a preload script in this way:
// main process script
const mainWindow = new BrowserWindow({
webPreferences: {
contextIsolation: false,
nodeIntegration: false,
preload: './preload.js'
}
})
mainWindow.loadURL('my-safe-file.html')
// preload.js
const { readFileSync } = require('fs')
// the host page will have access to `window.readConfig`,
// but not direct access to `readFileSync`
window.readConfig = function () {
const data = readFileSync('./config.json')
return data
}
// renderer.js
const config = window.readConfig()
如果您只加载本地页面,并且这些页面不加载或执行不安全的动态内容,那么您可能重新考虑在此策略中使用 contextIsolation
.但是,如果您想保持 contextIsolation
开启(如果您有机会显示不安全的内容,您肯定应该这样做),您只能使用 通过 postMessage
传递的消息.
If you're only loading local pages, and those pages don't load or execute unsafe dynamic content then you might reconsider the use of contextIsolation
for this strategy. If you want to keep contextIsolation
on, however (and you definitely should if you have a chance of showing unsafe content), you can only communicate with the preload script with message passing via postMessage
.
这是上述相同场景的示例,但启用了 contextIsolation
并使用消息传递.
Here's an example of the same scenario above, but with contextIsolation
on and using message passing.
// main process script
const mainWindow = new BrowserWindow({
webPreferences: {
contextIsolation: true,
nodeIntegration: false,
preload: './preload.js'
}
})
mainWindow.loadURL('my-unsafe-file.html')
// preload.js
const { readFileSync } = require('fs')
const readConfig = function () {
const data = readFileSync('./config.json')
return data
}
window.addEventListener('message', (event) => {
if (event.source !== window) return
if (event.data.type === 'request') {
window.postMessage({ type: 'response', content: readConfig() })
}
})
// renderer.js
window.addEventListener('message', (event) => {
if (event.source !== window) return
if (event.data.type === 'response') {
const config = event.data.content
}
})
window.postMessage('request')
虽然这肯定更冗长且难以处理(并迫使事情异步,因为消息传递是异步的),但它也更安全.postMessage
API 周围的一对小型 JS 包装器可以使这更容易使用(例如通过类似 RPC 的机制),但请记住使用 contextIsolation
的全部意义是因为你不能信任渲染器,所以你的预加载脚本不应该只信任它通过 postMessage
API 获得的任何消息——你应该始终验证你收到的事件以确保你信任它.
While this is definitely more verbose and difficult to deal with (and forces things to be async, because message passing is async), it's also much more secure. A pair of small JS wrappers around the postMessage
API could make this easier to work with (e.g. via an RPC-like mechanism), but remember that the whole point of using contextIsolation
is because you can't trust the renderer, so your preload script shouldn't trust just any message it gets via the postMessage
API — you should always verify the event that you receive to ensure that you trust it.
此幻灯片 描述者详细说明为什么在不使用上下文隔离的情况下关闭 Node 集成并不总是一个好主意.
This slide deck describers in detail why turning off Node integration without using context isolation is not always a good idea.
这篇关于电子“要求未定义";的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!