Perché escape_javascript prima del rendering parziale?

Sto guardando questo episodio di Railscast e mi chiedo perché la chiamata a escape_javascript sia necessaria qui:

 $("#reviews").append(" @review)) %>"); 

A cosa serve escape_javascript ?

Secondo i documenti di Rails :

escape_javascript (javascript)

Restituzioni del vettore di fuga e virgolette singole e doppie per i segmenti JavaScript.

Ma questo non significa molto per me.

Perché non vuoi che gli utenti pubblichino JavaScript che il browser effettivamente esegue?

È più facile capire se dividi il codice in due parti.

La prima parte $("#reviews").append("<%= ... %>"); è javascript con erb. Ciò significa che <%= ... %> sarà sostituito da qualunque sia il codice ruby al suo interno. Il risultato di tale sostituzione deve essere javascript valido, altrimenti genererà un errore quando il client tenta di elaborarlo. Quindi questa è la prima cosa: hai bisogno di un javascript valido .

Un’altra cosa da tenere in considerazione è che qualunque cosa generi ruby ​​deve essere contenuta all’interno di una stringa javascript con virgolette doppie – nota le doppie virgolette attorno al <%= ... %> . Ciò significa che il javascript generato sarà simile al seguente:

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

Ora esaminiamo la parte ruby all’interno di <%= ... %> . Che cosa fa render(:partial => @review) ? Si tratta di un rendering parziale – il che significa che potrebbe essere il rendering di qualsiasi tipo di codice: html, css … o anche più javascript!

Quindi, cosa succede se il nostro partial contiene qualche semplice html, come questo?

 Action! 

Ricorda che il tuo javascript stava prendendo una stringa doppia citazione come parametro? Se sostituiamo semplicemente <%= ... %> con il codice di quel partial, allora abbiamo un problema – immediatamente dopo href= c’è una doppia citazione! Il javascript non sarà valido:

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

Affinché questo non accada, vuoi sfuggire a questi caratteri speciali in modo che la tua stringa non sia tagliata – hai bisogno di qualcosa che generi questo invece:

 Action! 

Questo cosa fa escape_javascript . Si assicura che la stringa restituita non “spezzerà” javascript. Se lo usi, otterrai l’output desiderato:

 $("#reviews").append("Action!") 

Saluti!

gli utenti possono inserire codice malevolo (utenti malintenzionati) che, se lasciato senza caratteri di escape, verrà potenzialmente eseguito, consentendo agli utenti di controllare la propria applicazione.

prova questo:

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

Non ho molta familiarità con la syntax delle rotaie, ma se non esci da una variable , verrà visualizzata una finestra di avviso, e non penso che sia il comportamento previsto.

Se guardi la fonte qui , sarà molto più chiara.

Questa funzione realizza le seguenti due cose:

  1. Sostituisce i caratteri nella stringa di input con quelli definiti in JS_ESCAPE_MAP

    Lo scopo di questo è di assicurarsi che il codice javascript sia serializzato correttamente senza interferire con la stringa esterna all’interno della quale viene incorporato. Ad esempio se hai una stringa javascript tra virgolette doppie tutte le virgolette interne per stringhe letterali devono essere racchiuse tra virgolette singole per evitare che il codice si spezzi.

  2. La funzione controlla anche se la stringa risultante è html sicura. Se non lo è, esegue l’escape necessario per assicurarsi che la stringa diventi html sicura e restituisca il risultato.

Quando si utilizza escape_javascript, in genere viene incorporato in un’altra stringa o in html esistente in modo dinamico. Devi assicurarti che ciò non impedisca il rendering dell’intera pagina.

Alcuni aspetti di questa risposta sono stati evidenziati in altre risposte ma volevo che tutti gli elementi includessero la differenza tra l’escape di javascript e l’escape di html. Inoltre, alcune risposte suggeriscono che questa funzione aiuta ad evitare l’iniezione di script. Non penso che sia lo scopo di questa funzione. Ad esempio, nella tua recensione se la tua recensione ha un avviso (‘Ciao là’), semplicemente aggiungendolo al nodo non si triggers il pop-up. Non lo si incorpora all’interno di una funzione triggersta al caricamento della pagina o attraverso altri eventi. Il solo fatto di avere un avviso (‘Ciao là’) come parte del tuo html non significa che verrà eseguito come javascript.

Detto questo, non sto negando che l’iniezione di script non è ansible. Ma per evitare che è necessario prendere provvedimenti quando si prendono i dati utente e li memorizzano nel database. La funzione e l’esempio che stai fornendo sono relativi al rendering delle informazioni, che erano già state salvate.

Spero che questo aiuti e risponda alla tua domanda.

Non eseguirà il javascript di ciò che stai rendendo