JavaScript-Sandbox-Erkundung

JavaScript-Sandbox-Erkundung

1. Szenario

Ich habe kürzlich an etwas Ähnlichem wie einem webbasierten Plug-in-System gearbeitet und dabei mit der JS-Sandbox herumgespielt, um Code aus Drittanbieteranwendungen auszuführen.

2. Grundfunktionen der Sandbox

Vor der Implementierung (oder eigentlich nach der Recherche einiger Lösungen) wurde festgelegt, dass die Sandbox die Funktionen der oberen Ebene basierend auf event bus Kommunikation implementieren würde. Die grundlegende Schnittstelle ist wie folgt

Schnittstelle IEventEmitter exportieren {
  /**
   * Abhörereignis * @param-Kanal
   * @param-Handle
   */
  ein (Kanal: Zeichenfolge, Handle: (Daten: beliebig) => ungültig): ungültig;

  /**
   * Abhören abbrechen * @param channel
   */
  offByChannel(Kanal: Zeichenfolge): void;

  /**
   * Ereignis auslösen * @param Kanal
   * @param-Daten
   */
  emittieren (Kanal: Zeichenfolge, Daten: beliebig): ungültig;
}

/**
 * Eine grundlegende JS-VM-Funktion */
Exportschnittstelle IJavaScriptShadowbox erweitert IEventEmitter {
  /**
   * Beliebigen Code ausführen * @param Code
   */
  eval(Code: Zeichenfolge): ungültig;

  /**
   * Zerstöre die Instanz */
  zerstören(): ungültig;
}

Neben der Fähigkeit zur Kommunikation sind zwei weitere Methoden erforderlich:

  • eval : Führe einen Teil des JS-Codes aus
  • destroy : Zerstören Sie die Sandbox, damit die interne Implementierung einige Bereinigungsaufgaben erledigen kann.

JavaScript-Sandbox-Diagramm:

Im Folgenden zeigen wir, wie man mit iframe/web worker/quickjs beliebige js ausführt

3. Iframe-Implementierung

Ehrlich gesagt, wenn man über Sandboxen im Web spricht, denkt man wahrscheinlich als Erstes an iframe , aber es verwendet als Einstiegsdatei html statt JS, was nicht sehr benutzerfreundlich ist für Szenarien, in denen Sie JS als Einstieg verwenden möchten, aber nicht unbedingt iframe anzeigen müssen.

Natürlich können Sie den JS-Code in HTML einbinden und dann ausführen

Funktion evalByIframe(Code: Zeichenfolge) {
  const html = `<!DOCTYPE html><body><script>$[code]</script></body></html>`;
  const iframe = document.createElement("iframe");
  iframe.Breite = "0";
  iframe.Höhe = "0";
  iframe.style.display = "keine";
  Dokument.body.appendChild(iframe);
  const blob = neuer Blob([html], { Typ: "text/html" });
  iframe.src = URL.createObjectURL(blob);
  Iframe zurückgeben;
}

evalByIframe(`
document.body.innerHTML = "Hallo Welt"
Konsole.log('Standort.href: ', Standort.href)
Konsole.log('lokaler Speicher: ',lokaler Speicher)
`);

Aber iframe hat die folgenden Probleme:

  • Fast dasselbe wie eval (verwendet hauptsächlich Object.createObjectURL , was zu Homologie führt) – fatal
  • Kann auf alle Browser api – Wir bevorzugen, nur auf die eingefügten api zugreifen zu können, nicht auf alle dom api

4. Web Worker-Implementierung

Ein web worker ist grundsätzlich eine eingeschränkte JS-Laufzeitumgebung, die JS als Einstiegspunkt verwendet und über einen Kommunikationsmechanismus verfügt, der dem iframe

Funktion evalByWebWorker(Code: Zeichenfolge) {
  const blob = neuer Blob([Code], { Typ: "Anwendung/Javascript" });
  const url = URL.createObjectURL(blob);
  gib neuen Worker(URL) zurück;
}

evalByWebWorker(`
Konsole.log('Standort.href: ', Standort.href)
// console.log('localStorage: ', localStorage)
`);

Aber gleichzeitig ist es tatsächlich besser als iframe

  • Es werden nur begrenzte Browser-APIs unterstützt, darunter localStorage/document APIs, auf die nicht zugegriffen werden kann. Weitere Einzelheiten finden Sie unter: [MDN] Funktionen und Klassen, die von Web Workern verwendet werden können
  • Alle eingefügten APIs sind schließlich asynchrone Vorgänge, die auf postMessage/onmessage basieren.

5. Quickjs-Implementierung

Die Hauptinspiration für die Verwendung quickjs stammt aus einem Blogbeitrag über das Plugin-System von Figma, der chinesischen Quickjs-Dokumentation

Was ist Quickjs? Es handelt sich um eine JavaScript-Laufzeitumgebung. Die von uns am häufigsten verwendeten Laufzeitumgebungen sind zwar Browser und nodejs , es gibt jedoch noch viele andere. Weitere finden Sie unter GoogleChromeLabs/jsvu. quickjs ist eine leichte, eingebettete Laufzeitumgebung, die die Kompilierung in wasm unterstützt und im Browser ausgeführt wird. Es unterstützt auch JS-Funktionen bis zu es2020 (einschließlich der beliebten Promise und async/await ).

asynchrone Funktion evalByQuickJS(Code: Zeichenfolge) {
  const quickJS = warte auf getQuickJS();
  const vm = quickJS.createVm();
  const res = vm.dump(vm.unwrapResult(vm.evalCode(code)));
  vm.dispose();
  Rückgabewert;
}

 
console.log(warte auf evalByQuickJS(`1+1`));

Vorteil:

  • Tatsächlich ist es in puncto Sicherheit unübertroffen, da es auf verschiedenen vm ausgeführt wird und es kaum zu Sicherheitsproblemen kommt, die bei vorhandenen, auf Proxy basierenden Mikro-Frontends auftreten können.
  • Obwohl es keinen tatsächlichen Test gibt, weist der Blogbeitrag von figma darauf hin, dass das strukturierte Klonen des Browsers bei der Verarbeitung großer Objekte Leistungsprobleme aufweist, während dieses Problem quickjs nicht auftritt.

Mangel:

  • Es gibt keine globale api , einschließlich der gemeinsamen console/setTimeout/setInterval die keine Funktionen von js sind, sondern vom Browser und nodejs -Laufzeit implementiert werden. Sie müssen daher manuell implementiert und eingefügt werden, was einen erheblichen Nachteil darstellt.
  • Das DevToo Debugging des Browsers kann nicht verwendet werden
  • Da die zugrunde liegende Implementierung in C erfolgt, muss die Speicherfreigabe manuell verwaltet werden.

6. Fazit

Schließlich haben wir uns entschieden, den EventEmitter von Web Worker und QuickJS basierend auf der Schnittstelle zu implementieren und die Möglichkeit zu unterstützen, jederzeit wechseln zu können.

Dies ist das Ende dieses Artikels über die Erkundung von JavaScript-Sandboxen. Weitere relevante JavaScript-Sandbox-Inhalte finden Sie in den vorherigen Artikeln von 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

Das könnte Sie auch interessieren:
  • Quickjs kapselt JavaScript-Sandbox-Details
  • Ein kurzer Vortrag über JavaScript Sandbox
  • Eine kurze Diskussion über verschiedene Möglichkeiten zur Implementierung einer Front-End-JS-Sandbox
  • Eine kurze Diskussion über die Node.js-Sandbox-Umgebung
  • Einrichten einer sicheren Sandbox-Umgebung für Node.js-Anwendungen
  • Beispiel für den Sandbox-Modus beim Schließen der JS-Implementierung
  • Beispielanalyse des JS-Sandbox-Modus
  • Sicherheits-Sandbox-Modus des JavaScript-Entwurfsmusters
  • WebWorker kapselt JavaScript-Sandbox-Details

<<:  Detaillierte Erläuterung der CSS BEM-Schreibstandards

>>:  Detaillierte Erklärung des MySQL-Triggerbeispiels

Artikel empfehlen

Vue realisiert den Gleitkreuzeffekt des Balles

In diesem Artikelbeispiel wird der spezifische Co...

Kopieren und Einfügen ist der Feind der Verpackung

Bevor wir über OO, Entwurfsmuster und die vielen o...

Detaillierte Erklärung des Unterschieds zwischen Docker-Compose-Ports und Expose

Es gibt zwei Möglichkeiten, Container-Ports in Do...

Zwei Möglichkeiten zum Öffnen und Schließen des MySQL-Dienstes

Methode 1: Verwenden Sie den cmd-Befehl Öffnen Si...

Probleme und Lösungen bei der Installation von Mininet auf Ubuntu 16.04.4LTS

Mininet Mininet ist eine leichtgewichtige, softwa...

...

Implementierung einer geplanten Sicherung in Mysql5.7

1. Suchen Sie mysqldump.exe im MySQL-Installation...

CSS3 realisiert Partikelanimationseffekte beim Matching von Königen

Beim Codieren werden Sie feststellen, dass viele ...

jQuery-Plugin zum Erreichen einer Bildunterbrechung

In diesem Artikel wird der spezifische Code des j...

So erstellen Sie einen pptpd-Dienst in Alibaba Cloud Ubuntu 16.04

1. Um ein PPTP-VPN aufzubauen, müssen Sie Port 17...

Zusammenfassung der MySQL-Ansichtsprinzipien und Anwendungsbeispiele

Dieser Artikel fasst die Prinzipien und die Verwe...