2009-10-25 21 views
110

Sto guardando this Railscast episode e si chiede perché è necessaria la chiamata a escape_javascript qui:Perché escape_javascript prima del rendering parziale?

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

Cos'è escape_javascript utilizzato per?

Secondo the Rails docs:

escape_javascript (javascript)

carrier fuga rendimenti e singola e doppi apici per i segmenti JavaScript.

Ma questo non significa molto per me.

+19

Cordiali saluti, la risposta accettata qui non è la risposta corretta. Kikito's è – Steve

risposta

1

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

+4

Ma che ne dici di quando vuoi passare e visualizzare il codice javascript? – berto77

+0

Sì, in realtà è più di un metodo di formattazione.Non impedisce agli utenti di eseguire il proprio javascript. Niente può impedirlo. – Deviljho

+2

Questo non è utile. Vedi [risposta di kikito] (http://stackoverflow.com/a/1623813/703233). – nitsas

8

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.

provare questo:

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

realtà non familiarità con la sintassi di rotaie, ma se non fuggire variable quindi una finestra di avviso mostrerà, e non penso che sia il comportamento desiderato.

327

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

La prima parte $("#reviews").append("<%= ... %>"); è javascript con erb. Ciò significa che lo <%= ... %> verrà sostituito da qualunque sia il codice rubino 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 dello javascript valido.

Un'altra cosa da tenere in considerazione è che qualsiasi rubino generato deve essere contenuto all'interno di una stringa javascript con virgolette doppie: notare le doppie virgolette attorno allo <%= ... %>. Ciò significa che il javascript generato sarà simile a questa:

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

Ora esaminiamo la parte rubino all'interno del <%= ... %>. 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 un semplice html, come questo?

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

Ricordate che il vostro javascript stava prendendo una stringa doppia virgola come parametro? Se sostituiamo semplicemente il <%= ... %> con il codice di quel parziale, allora abbiamo un problema - immediatamente dopo lo href= c'è una doppia citazione!Il javascript non sarà valido:

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

Affinché ciò non accada, si vuole fuga questi caratteri speciali in modo che lo stringa non è tagliato - avete bisogno di qualcosa che genera questo, invece:

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

Ciò che fa escape_javascript. Si assicura che la stringa restituita non "spezzerà" javascript. Se lo usi, otterrai l'output desiderato:

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

Saluti!

+4

davvero, molto bella spiegazione grazie. Immagino che usare 'escape_javascript' sia un po 'fuorviante perché non lo stiamo effettivamente utilizzando per evitare il javascript reale. Puoi inserire un tag script nel partial ed eseguire qualsiasi javascript che desideri. – Steve

+12

Accetto @Steve, un nome migliore sarebbe 'escape_for_javascript', poiché spesso si sta eseguendo l'escape di altro codice (ad esempio html) in modo che non si rompa javascript. – kikito

+13

'escape_javascript()' ha ora un metodo più breve: simpley 'j()' (almeno in Rails 4). – mjnissim

7

Se si guarda la fonte here, sarà molto più chiaro.

Questa funzione realizza le seguenti due cose:

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

    Lo scopo di questo è di assicurarsi che il codice JavaScript è serializzato correttamente senza interferire con la stringa esterna all'interno della quale viene incorporata. Ad esempio se hai una stringa javascript tra virgolette doppie allora tutte le virgolette interne per i valori letterali di stringa devono essere racchiuse tra virgolette singole per evitare che il codice subisca un'interruzione di .

  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'escaping 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 attiva il pop-up. Non lo si incorpora all'interno di una funzione attivata 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'inserimento di script non è possibile. 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.

-3

Non eseguirà il javascript di ciò che si sta eseguendo il rendering

Problemi correlati