Electron迁移服务端代码到渲染进程触发unsafe-eval错误如何解决?
问题解决方法
根因说明
- 架构错误:Express、Socket.IO服务端属于Node.js服务端逻辑,应当放在Electron主进程运行,你将其放入HTML引入的渲染进程执行,违反了Electron的进程职责划分
- CSP限制:渲染进程默认启用Content Security Policy,默认规则禁止
unsafe-eval动态代码执行,你依赖的depd、body-parser等服务端模块用到了动态函数生成,触发了该限制
最优解决方案(推荐)
纠正架构,通过IPC通信实现渲染进程触发主进程的服务启停操作:
1. 主进程改造(main.js)
把你的服务逻辑全部移到主进程,通过ipcMain监听渲染进程的启停请求:
const { app, BrowserWindow, ipcMain, path } = require('electron') // 全局保存服务实例,避免重复启动 let httpServer = null let io = null // 启动服务逻辑 ipcMain.handle('start-server', async () => { if (httpServer) return { success: true, msg: '服务已运行' } try { const expresso = require("express") const limpador = require("string-sanitizer") const appe = expresso() httpServer = require("http").createServer(appe) io = require("socket.io")(httpServer, {}) appe.use(expresso.static(__dirname + "/data")) httpServer.listen(8889, () => console.log("服务已启动,端口8889")) io.on("connection", (socket) => { console.log("新连接,ID:", socket.id) socket.on("manda", (arg) => { limpador.sanitize.keepSpace(arg) console.log("收到消息:", arg) socket.broadcast.emit("devolve", arg) socket.emit("devolve", arg) }) }) return { success: true } } catch (err) { return { success: false, msg: err.message } } }) // 停止服务逻辑按需补充 // 原有创建窗口的逻辑保留,创建窗口时无需开启不安全的node集成 function createWindow () { const mainWindow = new BrowserWindow({ width: 800, height: 600, webPreferences: { // 保持默认安全配置即可 preload: path.join(__dirname, 'preload.js') } }) mainWindow.loadFile('index.html') }
2. 渲染进程改造(你原来的Server.js)
移除所有服务端逻辑,只保留UI交互和IPC调用:
const { ipcRenderer } = require('electron') const ligar_desligar = document.getElementById("botao3") let statusServer = false ligar_desligar.addEventListener('click', async () => { if (!statusServer) { const res = await ipcRenderer.invoke('start-server') if (res.success) { statusServer = true ligar_desligar.innerText = '关闭私有服务器' } } else { // 调用停止服务的IPC接口即可 } })
临时兼容方案(不推荐生产使用)
如果暂时不想调整架构,需要快速验证功能,可修改配置放开限制:
- 修改HTML的CSP meta标签,添加
unsafe-eval权限:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'">
- 创建BrowserWindow时开启Node集成并关闭上下文隔离:
const mainWindow = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true, contextIsolation: false } })
注意:该方案存在严重安全风险,只要渲染进程加载了不可信的第三方代码,攻击者可直接获取你本地系统的全部权限,仅可用于本地功能测试。
内容的提问来源于stack exchange,提问作者GNLages
相关产品推荐
相关产品推荐

