Warum Escape_Javascript vor dem Rendern eines Teils?

120

Ich schaue mir diese Railscast-Episode an und frage mich, warum der Anruf escape_javascripthier benötigt wird:

$("#reviews").append("<%= escape_javascript(render(:partial => @review)) %>");

Wofür wird escape_javascriptverwendet?

Laut den Rails-Dokumenten :

Escape_Javascript (Javascript)

Escape Carrier kehrt zurück und einfache und doppelte Anführungszeichen für JavaScript-Segmente.

Das bedeutet mir aber nicht viel.


quelle
23
Zu Ihrer Information, die hier akzeptierte Antwort ist nicht die richtige Antwort. Kikito ist
Steve

Antworten:

-3

Weil Sie nicht möchten, dass Benutzer JavaScript veröffentlichen, das der Browser tatsächlich ausführt?

Azeem.Butt
quelle
4
Aber wie wäre es, wenn Sie Javascript-Code übergeben und rendern möchten?
Berto77
Ja, eigentlich ist es eher eine Formatierungsmethode. Es hindert Benutzer nicht daran, ihr eigenes Javascript auszuführen. Nichts kann das verhindern.
LasagneAndroid
3
Das ist nicht hilfreich. Siehe stattdessen Kikitos Antwort .
Nitsas
362

Es ist einfacher zu verstehen, wenn Sie den Code in zwei Teile teilen.

Der erste Teil $("#reviews").append("<%= ... %>");ist Javascript mit erb. Dies bedeutet, dass der <%= ... %>durch den darin enthaltenen Ruby-Code ersetzt wird. Das Ergebnis dieser Ersetzung muss gültiges Javascript sein, andernfalls wird ein Fehler ausgegeben, wenn der Client versucht, ihn zu verarbeiten. Das ist also das Erste: Sie benötigen gültiges Javascript .

Eine andere Sache, die berücksichtigt werden muss, ist, dass alles, was Ruby erzeugt, in einer Javascript-Zeichenfolge mit doppelten Anführungszeichen enthalten sein muss - beachten Sie die doppelten Anführungszeichen um das <%= ... %>. Dies bedeutet, dass das generierte Javascript folgendermaßen aussieht:

$("#reviews").append("...");

Lassen Sie uns nun den Rubinteil im Inneren untersuchen <%= ... %>. Was macht render(:partial => @review)das Es wird ein Teil gerendert - was bedeutet, dass es jede Art von Code rendern kann - HTML, CSS ... oder noch mehr Javascript!

Was passiert also, wenn unser Teil ein einfaches HTML wie dieses enthält?

<a href="/mycontroller/myaction">Action!</a> 

Denken Sie daran, dass Ihr Javascript eine Zeichenfolge in doppelten Anführungszeichen als Parameter verwendet hat? Wenn wir das einfach durch den <%= ... %>Code dieses Teils ersetzen , haben wir ein Problem - unmittelbar danach href=gibt es ein doppeltes Anführungszeichen! Das Javascript ist ungültig:

// Without escaping, you get a broken javascript string at href
$("#reviews").append("<a href="/mycontroller/myaction">Action!</a>");

Damit dies nicht passiert, möchten Sie diesen Sonderzeichen entkommen , damit Ihre Zeichenfolge nicht abgeschnitten wird. Stattdessen benötigen Sie etwas, das dies generiert:

<a href=\"/mycontroller/myaction\">Action!</a>

Das was escape_javascriptmacht. Es stellt sicher, dass die zurückgegebene Zeichenfolge kein Javascript "bricht". Wenn Sie es verwenden, erhalten Sie die gewünschte Ausgabe:

$("#reviews").append("<a href=\"/mycontroller/myaction\">Action!</a>")

Grüße!

Kikito
quelle
4
in der Tat sehr schöne Erklärung danke. Ich denke, dann ist die Verwendung von 'Escape_Javascript' irreführend, da wir es nicht verwenden, um tatsächlichem Javascript zu entkommen. Sie können ein Skript-Tag in den Teil einfügen und jedes gewünschte Javascript ausführen.
Steve
13
@Steve stimmte zu, ein besserer Name wäre escape_for_javascript, da Sie häufig anderen Code (z. B. HTML) entkommen, damit kein Javascript beschädigt wird.
Kikito
14
escape_javascript()hat jetzt eine kürzere Methode: simpley j()(mindestens in Rails 4).
mjnissim
@kikito, versuche ich mit diesem Effekt, einen HTML-Teil zu rendern, der aus einem entfernten Formular besteht? Ich versuche herauszufinden, warum das Rendern eines Teils mit Javascript, das ein anderes Formular enthält, das über Javascript gesendet wird, dazu führt, dass die zweite Anforderung HTML anstelle von js ist. Wenn Sie Zeit haben, können Sie sich bitte die Frage ansehen, die ich bereits dazu gestellt habe. Vielen Dank! Meine Frage
Jake Smith
1
@ JakeSmith antwortete in Ihrer Frage
Kikito
8

Benutzer können bösartigen Code (böswillige Benutzer) veröffentlichen, der möglicherweise ausgeführt wird, wenn er nicht entführt wird, sodass Benutzer Ihre Anwendung steuern können.

Versuche dies:

<% variable = '"); alert("hi there' %>
$("#reviews").append("<%= variable %>");

variableIch bin nicht wirklich mit der Syntax von Schienen vertraut, aber wenn Sie nicht entkommen, wird eine Warnmeldung angezeigt, und ich glaube nicht, dass dies beabsichtigtes Verhalten ist.

Barkmadley
quelle
8

Wenn Sie sich die Quelle hier ansehen , wird es viel klarer.

Diese Funktion führt die folgenden zwei Dinge aus:

  1. Es ersetzt die Zeichen in der Eingabezeichenfolge durch die in JS_ESCAPE_MAP definierten

    Damit soll sichergestellt werden, dass der Javascript-Code korrekt serialisiert wird, ohne die äußere Zeichenfolge zu beeinträchtigen, in die er eingebettet wird. Wenn Sie beispielsweise eine Javascript-Zeichenfolge in doppelten Anführungszeichen haben, müssen alle Anführungszeichen für Zeichenfolgenliterale in einfachen Anführungszeichen stehen, damit der Code nicht beschädigt wird.

  2. Die Funktion prüft auch, ob die resultierende Zeichenfolge HTML-sicher ist. Ist dies nicht der Fall, wird das erforderliche Escapezeichen ausgeführt, um sicherzustellen, dass die Zeichenfolge HTML-sicher wird und das Ergebnis zurückgibt.

Wenn Sie Escape_Javascript verwenden, wird es normalerweise dynamisch in eine andere Zeichenfolge oder ein vorhandenes HTML eingebettet. Sie müssen sicherstellen, dass dadurch nicht Ihre gesamte Seite gerendert wird.

Einige Aspekte dieser Antwort wurden in anderen Antworten hervorgehoben, aber ich wollte alle Elemente zusammenführen, einschließlich des Unterschieds zwischen Javascript-Escape und HTML-Escape. Einige Antworten weisen auch darauf hin, dass diese Funktion dazu beiträgt, das Einfügen von Skripten zu vermeiden. Ich denke nicht, dass dies der Zweck dieser Funktion ist. Wenn Ihre Bewertung beispielsweise in Ihrer Bewertung eine Warnung enthält ("Hallo"), wird das Popup nicht ausgelöst, wenn Sie sie nur an den Knoten anhängen. Sie binden es nicht in eine Funktion ein, die beim Laden der Seite oder durch ein anderes Ereignis ausgelöst wird. Nur eine Warnung ('hi there') als Teil Ihres HTML-Codes zu haben, bedeutet nicht, dass es als Javascript ausgeführt wird.

Trotzdem leugne ich nicht, dass eine Skriptinjektion nicht möglich ist. Um dies zu vermeiden, müssen Sie Schritte unternehmen, wenn Sie die Benutzerdaten in Ihrer Datenbank speichern. Die von Ihnen bereitgestellte Funktion und das Beispiel beziehen sich auf das Rendern der Informationen, die bereits gespeichert wurden.

Ich hoffe das hilft und beantwortet deine Frage.

Tabrez
quelle