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

Detailliertes Beispiel für die JSON-Analyse mit MySQL (5.6 und darunter)

MySQL (5.6 und darunter) analysiert JSON #json-An...

Windows kann den MySQL-Dienst nicht starten und meldet Fehler 1067 – Lösung

Als ich mich bei MySQL anmeldete, wurde mir plötz...

So richten Sie einen URL-Link im Nginx-Server ein

Websites mit einer Architektur wie LNMP werden im...

Detaillierte Erklärung der Fallstricke von MySQL 8.0

Ich habe heute MySQL 8.0 aktualisiert. Das erste ...

Beispiel für das Erstellen eines virtuellen Hosts basierend auf dem Apache-Port

Apache: Virtuellen Host basierend auf Port erstel...

Optimieren Sie MySQL mit 3 einfachen Tricks

Ich erwarte nicht, ein erfahrener Datenbankadmini...

Detaillierte Erläuterung des Shared-Memory-Mechanismus von Nginx

Der gemeinsam genutzte Speicher von Nginx ist ein...

Das Prinzip und die Implementierung des JS-Drag-Effekts

Die Drag-Funktion wird hauptsächlich verwendet, u...

Nginx Reverse Proxy Springboot JAR-Paket-Prozessanalyse

Die übliche Methode zum Bereitstellen eines Sprin...

Erfahren Sie, wie Sie Vue3 Reactivity implementieren

Inhaltsverzeichnis Vorwort Start Ein kleiner Geda...

Lösung zum automatischen Neustart von MySQL

Vorwort Kürzlich trat in der Testumgebung ein Pro...