전자 요구()가 정의되지 않았습니다.
저는 제 목적을 위해 Electron 앱을 만들고 있습니다.문제는 HTML 페이지에서 노드 함수를 사용할 때 다음과 같은 오류가 발생한다는 것입니다.
'flash()'는 정의되어 있지 않습니다.
모든 HTML 페이지에서 노드 기능을 사용할 수 있는 방법이 있습니까?가능하다면, 그 방법의 예나 링크를 가르쳐 주세요.HTML 페이지에서 사용하려는 변수는 다음과 같습니다.
var app = require('electron').remote;
var dialog = app.dialog;
var fs = require('fs');
이것들은 Electron의 모든 HTML 창에서 사용하고 있는 값입니다.
로는 '5'입니다.nodeIntegration
참말브라우저 창을 만들 때 활성화할 수 있습니다.
app.on('ready', () => {
mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
}
});
});
2022년 편집
저는 Electron의 역사에 대해 더 많은 글을 올렸습니다.Electron은 다양한 프레임워크 버전에서 보안에 접근하는 방법(그리고 취해야 할 최선의 접근법)에 영향을 미치는 추가 컨텍스트를 제공합니다.
원답
이 답변이 주목받기를 바랍니다. 왜냐하면 대부분의 답변이 당신의 전자 앱에 큰 보안 구멍을 남기기 때문입니다.사실 이 답변은 기본적으로 여러분이 사용해야 할 것입니다.require()
더 할 수 있는 전자 API가 .) (v7에서는 조금 깔끔하게 할 수
나는 당신이 할 수 있는 방법에 대한 가장 최신 전자 아피스를 사용하여 github에 상세한 설명/솔루션을 썼다.require()
여기에서는 프리로드 스크립트, contextBridge 및 ipc를 사용하는 접근방식을 따라야 하는 이유를 간단히 설명하겠습니다.
문제
전자 앱은 노드를 사용할 수 있기 때문에 훌륭하지만, 이 힘은 양날의 칼입니다.주의하지 않으면 앱을 통해 노드에 접속할 수 있게 됩니다.노드를 사용하면 불량 행위자가 기기를 손상시키거나 운영체제 파일을 삭제할 수 있습니다(다른 것).
@raddevus가 댓글로 제기한 것처럼 리모트콘텐츠를 로드할 때 필요합니다.전자 앱이 완전히 오프라인/로컬인 경우 켜기만 하면 됩니다.
nodeIntegration:true
하지만, 난 여전히 이 모든 것들을nodeIntegration:false
또는 발생 를 보호하는 역할을 , 에 설치될 수하여 전자 앱을 하는 것을 합니다.nodeIntegration:true
공격 벡터(매우 드물지만 발생할 수 있음)!
문제의 외관
이 문제는 다음 중 하나에서 발생합니다.
- 갖고 있다
nodeIntegration:true
가능한 - 모듈 사용
이러한 모든 문제는 렌더러 프로세스에서 노드에 대한 중단 없는 액세스를 제공합니다.렌더러 프로세스가 납치된 경우 모든 것이 손실된 것으로 간주할 수 있습니다.
델의 솔루션
해결책은 렌더러에게 노드에 대한 직접 액세스 권한을 부여하지 않는 것입니다(즉, require()
). 하지만 우리의 전자 주요 프로세스 접근 권한을 부여하기 위해require
렌다라 프로세스가 필요할 때는 언제든지require
, 요구를 메인프로세스에 정리합니다.
Electron의 최신 버전(7+)에서의 동작 방법은 렌더러 측에서 ipcRenderer 바인딩을 설정하고 메인 측에서 ipcMain 바인딩을 설정합니다.ipcMain 바인딩에서는 모듈을 사용하는 청취자 메서드를 설정합니다.require()
이것은 좋습니다. 왜냐하면 우리의 주요 프로세스는require
원하는 만큼.
contextBridge를 사용하여 ipcRenderer 바인딩을 앱 코드에 전달합니다(사용할 수 있도록).따라서 앱이 이 바인딩을 사용할 필요가 있는 경우require
d modules는 주로 IPC(inter-process-communication)를 통해 메시지를 전송하고 메인 프로세스는 몇 가지 코드를 실행한 후 결과를 포함하여 메시지를 반환합니다.
대략, 당신이 원하는 것은 다음과 같습니다.
main.discloss.main.discloss.
const {
app,
BrowserWindow,
ipcMain
} = require("electron");
const path = require("path");
const fs = require("fs");
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win;
async function createWindow() {
// Create the browser window.
win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: false, // is default value after Electron v5
contextIsolation: true, // protect against prototype pollution
enableRemoteModule: false, // turn off remote
preload: path.join(__dirname, "preload.js") // use a preload script
}
});
// Load app
win.loadFile(path.join(__dirname, "dist/index.html"));
// rest of code..
}
app.on("ready", createWindow);
ipcMain.on("toMain", (event, args) => {
fs.readFile("path/to/file", (error, data) => {
// Do something with file contents
// Send result back to renderer process
win.webContents.send("fromMain", responseObj);
});
});
프리로드.js
const {
contextBridge,
ipcRenderer
} = require("electron");
// Expose protected methods that allow the renderer process to use
// the ipcRenderer without exposing the entire object
contextBridge.exposeInMainWorld(
"api", {
send: (channel, data) => {
// whitelist channels
let validChannels = ["toMain"];
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, data);
}
},
receive: (channel, func) => {
let validChannels = ["fromMain"];
if (validChannels.includes(channel)) {
// Deliberately strip event as it includes `sender`
ipcRenderer.on(channel, (event, ...args) => func(...args));
}
}
}
);
index.displaces를 표시합니다.
<!doctype html>
<html lang="en-US">
<head>
<meta charset="utf-8"/>
<title>Title</title>
</head>
<body>
<script>
window.api.receive("fromMain", (data) => {
console.log(`Received ${data} from main process`);
});
window.api.send("toMain", "some data");
</script>
</body>
</html>
부인
저는 전자 앱을 만드는 안전한 템플릿의 저자입니다.저는 이 주제에 관심이 있고, 몇 주 동안(현 시점에서는) 이 작업에 임하고 있습니다.
보안상의 이유로, 당신은 계속 보관해야 합니다.nodeIntegration: false
프리로드 스크립트를 사용하여 Node/Electron API에서 렌더러 프로세스(뷰)에 필요한 것을 윈도 변수를 통해 표시합니다.전자 문서:
""에 수 .
require
Node.('Node.js')
예
main.discloss.main.discloss.
const mainWindow = new BrowserWindow({
webPreferences: {
preload: path.join(app.getAppPath(), 'preload.js')
}
})
프리로드.js
const { remote } = require('electron');
let currWindow = remote.BrowserWindow.getFocusedWindow();
window.closeCurrentWindow = function(){
currWindow.close();
}
renderer.interval
let closebtn = document.getElementById('closebtn');
closebtn.addEventListener('click', (e) => {
e.preventDefault();
window.closeCurrentWindow();
});
우선, @Sathiraumesh 솔루션은 전자 애플리케이션에 큰 보안 문제를 남깁니다.앱이 에 몇 가지 추가 기능을 추가한다고 상상해 보십시오.messenger.com
예를 들어 읽지 않은 메시지가 있으면 도구 모음의 아이콘이 변경되거나 깜박입니다. 당신의 ★★★★★★★★★★★★★★★★★★★★★★★에main.js
브라우저 창(messenger.com).
app.on('ready', () => {
const mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: true
}
});
mainWindow.loadURL(`https://messengre.com`);
});
면 어쩌지messengre.com
컴퓨터에 해를 입히려는 악의적인 웹 사이트입니다.「 」를 설정했을 nodeIntegration: true
수 작업을 할 수 .
require('child_process').exec('rm -r ~/');
홈디렉토리가 사라졌어요
★★★★★★
모든 것이 아니라 필요한 것만 노출하세요.와 는ascript javascript 코드를 수 있습니다.require
★★★★★★★★★★★★★★★★★★.
// main.js
app.on('ready', () => {
const mainWindow = new BrowserWindow({
webPreferences: {
preload: `${__dirname}/preload.js`
}
});
mainWindow.loadURL(`https://messengre.com`);
});
// preload.js
window.ipcRenderer = require('electron').ipcRenderer;
// index.html
<script>
window.ipcRenderer.send('channel', data);
</script>
끔찍해.messengre.com
전체 파일 시스템을 삭제할 수 없습니다.
일렉트로닉스의 보안은 이렇게 진화한 것 같다(소스).
전자 1 노드연동 기본값은 true입니다.
렌더러는 노드 API에 대한 전체 액세스 권한을 가집니다. 렌더러는 원격 코드를 로드할 경우 큰 보안 위험이 있습니다.
전자 5 노드연동은 디폴트로 false입니다.
false로 설정하면 프리로드 스크립트를 사용하여 특정 API를 Renderer에 노출합니다(프리로드 스크립트는 노드 값에 관계없이 항상 노드 API에 액세스할 수 있습니다).통합)
//preload.js
window.api = {
deleteFile: f => require('fs').unlink(f)
}
Electron 5 context Isolation 기본값이 true입니다(실제로 Electron 11에서는 여전히 false 기본값이 됩니다).
이로 인해 프리로드 스크립트는 다른 컨텍스트에서 실행됩니다. 할 수 window.api = ...
하다
//preload.js
const { contextBridge } = require('electron')
contextBridge.exposeInMainWorld('api', {
deleteFile: f => require('fs').unlink(f)
})
6자 6 6 require()
노드는 .
에 'Drender'가 있는 sandbox
과 같이해야 . true로 설정하다.
//preload.js
const { contextBridge, remote } = require('electron')
contextBridge.exposeInMainWorld('api', {
deleteFile: f => remote.require('fs').unlink(f)
})
Electron 10 enable Remote Module 기본 false(Electron 12에서는 리모트모듈이 권장되지 않음)
remote
모듈은 샌드박스 렌더러에서 노드 API에 액세스해야 할 때(위의 예와 같이) 또는 메인 프로세스에서만 사용할 수 있는 Electron API(대화상자, 메뉴 등)에 액세스해야 할 때 사용합니다.remote
인 IPC
//preload.js
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('api', {
displayMessage: text => ipcRenderer.invoke("displayMessage", text)
})
//main.js
const { ipcMain, dialog } = require('electron')
ipcMain.handle("displayMessage", text => dialog.showMessageBox(text))
전자 10 권장 해제 노드통합 플래그(Electron 12에서 제거됨)
권고
「」를 설정해 주세요.{nodeIntegration: false, contextIsolation: true, enableRemoteModule: false}
.
, 「」를 설정합니다.{sandbox: true}
프리로드 스크립트는 IPC를 사용하여 메인 프로세스를 호출하여 모든 작업을 수행해야 합니다.
ifsandbox
입니다.는 노드 직접 할 수 는 false의 경우입니다.require('fs').readFile
이치
//bad
contextBridge.exposeInMainWorld('api', {
readFile: require('fs').readFile
})
사용하고 있습니까?nodeIntegration: false
Browser Window 초 browser 중? it it it it it it it it it it it it it it로 합니다.true
이란, (값)을 말합니다.true
를 참조해 주세요.
HTML이 아닙니다).<script> src="./index.js" </script>
<script>
require('./index.js')
</script>
튜토리얼을 따르기 때문에 html 페이지에 js파일이 필요했을 뿐입니다.다만, 리모트 모듈을 사용할 예정이기 때문에 보안이 가장 중요했습니다.저는 마이클의 답변을 수정해서 글을 올렸습니다.저처럼 '필요'에 대한 안전한 대안을 찾기 위해 몇 시간을 보낸 분들을 위해서요.코드가 틀리면 언제든지 지적해 주세요.
main.discloss.main.discloss.
const electron = require('electron');
const app=electron.app;
const BrowserWindow=electron.BrowserWindow;
const ipcMain=electron.ipcMain;
const path=require('path');
const url=require('url');
let win;
function createWindow(){
win=new BrowserWindow({
webPreferences:{
contextIsolation: true,
preload: path.join(__dirname, "preload.js")
}
});
win.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file',
slashes: true
}));
win.on('close', function(){
win=null
});
}
app.on('ready', createWindow);
프리로드.js
const electron=require('electron');
const contextBridge=electron.contextBridge;
contextBridge.exposeInMainWorld(
"api", {
loadscript(filename){
require(filename);
}
}
);
index.displaces를 표시합니다.
<!DOCTYPE html>
<html>
<head>
<title>Hello World App</title>
</head>
<body>
<h1>Hello World</h1>
<button id="btn">Click</button>
</body>
<script>
window.api.loadscript('./index.js');
</script>
</html>
index.displaces를 표시합니다.
const btn = document.getElementById('btn');
btn.addEventListener('click', function(){
console.log('button clicked');
});
특히 이것이 여전히 보안상의 위험을 내포하고 있는지 알고 싶습니다.감사해요.
보안 문제는 신경 쓰지 않고 브라우저 창에서 JavaScript에 의해 올바르게 해석되어야 하는 경우 main.js 코드에 추가 플래그를 붙입니다.
webPreferences: {
nodeIntegration: true,
nodeIntegrationInWorker: true,
nodeIntegrationInSubFrames: true,
enableRemoteModule: true,
contextIsolation: false //required flag
}
//rest of the code...
노드를 활성화해야 합니다.사용하기 위한 webPreferences의 통합.아래를 참조해 주세요.
const { BrowserWindow } = require('electron')
let win = new BrowserWindow({
webPreferences: {
nodeIntegration: true
}
})
win.show()
electron 5.0(리포지토리 공지)에서 breaking api 변경이 있었습니다.최신 버전 노드통합은 기본적으로 false로 설정되어 있습니다.
문서 Electron의 Node.js 통합으로 인해 DOM 모듈, export, require와 같은 추가 기호가 삽입됩니다.이로 인해 일부 라이브러리는 동일한 이름의 기호를 삽입하려고 하므로 문제가 발생합니다.이 문제를 해결하려면 Electron에서 노드 통합을 끌 수 있습니다.
그러나 Node.js와 Electron API를 사용할 수 있는 기능을 유지하려면 다른 라이브러리를 포함하기 전에 페이지의 기호 이름을 변경해야 합니다.
<head>
<script>
window.nodeRequire = require;
delete window.require;
delete window.exports;
delete window.module;
</script>
<script type="text/javascript" src="jquery.js"></script>
</head>
드디어 성공했어요.HTML 문서 스크립트 요소에 이 코드를 추가합니다.
답장이 늦어서 죄송합니다.저는 이것을 하기 위해 아래 코드를 사용합니다.
window.nodeRequire = require;
delete window.require;
delete window.exports;
delete window.module;
리고 and and를 사용하세요.nodeRequire
''를 사용하는 대신.require
.
정상적으로 동작합니다.
언급URL : https://stackoverflow.com/questions/44391448/electron-require-is-not-defined
'it-source' 카테고리의 다른 글
Python을 사용하여 cURL 명령을 실행하는 방법은 무엇입니까? (0) | 2022.11.20 |
---|---|
Swing GUI를 가장 잘 포지셔닝하는 방법 (0) | 2022.11.20 |
np.array()와 np.asarray()의 차이점은 무엇입니까? (0) | 2022.11.20 |
봄에 자기 인스턴스화 개체에 종속성을 주입하려면 어떻게 해야 합니까? (0) | 2022.11.20 |
행을 찾을 수 없는 경우 JOIN 조건의 폴백 값 (0) | 2022.11.20 |