¿Por qué escape_javascript antes de representar un parcial?

120

Estoy mirando este episodio de Railscast y me pregunto por qué escape_javascriptse necesita la llamada aquí:

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

¿Para qué se escape_javascriptusa?

De acuerdo con los documentos de Rails :

escape_javascript (javascript)

Escape del operador devuelve y comillas simples y dobles para segmentos de JavaScript.

Pero eso no significa mucho para mí.


fuente
23
FYI, la respuesta aceptada aquí no es la respuesta correcta. Kikito es
Steve

Respuestas:

-3

¿Porque no desea que los usuarios publiquen JavaScript que el navegador realmente ejecuta?

Azeem.Butt
fuente
44
Pero, ¿qué tal cuando quieres pasar y renderizar código javascript?
berto77
Sí, en realidad es más un método de formateo. No impide que los usuarios ejecuten su propio javascript. Nada puede evitar eso.
LasagnaAndroid
3
Esto no es útil. Ver la respuesta de kikito en su lugar.
nitsas
363

Es más fácil de entender si divide el código en dos partes.

La primera parte $("#reviews").append("<%= ... %>");es javascript con erb. Esto significa que <%= ... %>será reemplazado por lo que devuelva el código ruby ​​que contiene. El resultado de ese reemplazo debe ser javascript válido, de lo contrario arrojará un error cuando el cliente intente procesarlo. Así que eso es lo primero: necesitas JavaScript válido .

Otra cosa a tener en cuenta es que lo que sea que ruby ​​genere debe estar contenido dentro de una cadena de JavaScript con comillas dobles: observe las comillas dobles alrededor del <%= ... %>. Esto significa que el JavaScript generado se verá así:

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

Ahora examinemos la parte rubí dentro del <%= ... %>. ¿Qué render(:partial => @review)hacer? Está renderizando un parcial, lo que significa que podría representar cualquier tipo de código: html, css ... ¡o incluso más javascript!

Entonces, ¿qué sucede si nuestro parcial contiene algún html simple, como este?

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

¿Recuerdas que tu javascript estaba tomando una cadena entre comillas dobles como parámetro? Si simplemente reemplazamos el <%= ... %>con el código de ese parcial, entonces tenemos un problema, ¡inmediatamente después de que href=hay una comilla doble! El javascript no será válido:

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

Para que esto no suceda, desea escapar de estos caracteres especiales para que su cadena no se corte; necesita algo que genere esto en su lugar:

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

Esto lo que escape_javascripthace. Se asegura de que la cadena devuelta no "rompa" JavaScript. Si lo usa, obtendrá el resultado deseado:

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

¡Saludos!

kikito
fuente
44
de hecho, muy buena explicación gracias. Supongo que usar 'escape_javascript' es un poco engañoso porque en realidad no lo estamos usando para escapar de javascript real. Puede colocar una etiqueta de script en el parcial y ejecutar el javascript que desee.
Steve
13
@Steve estuvo de acuerdo, un mejor nombre sería escape_for_javascript, ya que a menudo se escapa de otro código (html, por ejemplo) para que no rompa javascript.
kikito
14
escape_javascript()ahora tiene un método más corto: simple j()(al menos en Rails 4).
mjnissim
@kikito, ¿al usar este efecto me está tratando de representar un html parcial que consiste en una forma remota? Estoy tratando de averiguar por qué representar un parcial con javascript que incluye otro formulario que se enviará a través de javascript hace que la segunda solicitud sea html en lugar de js. Si tiene tiempo, ¿podría mirar la pregunta que ya publiqué sobre esto? ¡Gracias! Mi pregunta
Jake Smith
1
@JakeSmith respondió a su pregunta
kikito
8

los usuarios pueden publicar código malicioso (usuarios maliciosos) que, si no se escapan, se ejecutarán potencialmente, lo que les permitirá controlar su aplicación.

prueba esto:

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

no estoy realmente familiarizado con la sintaxis de los rieles, pero si no escapa variable, aparecerá un cuadro de alerta, y no creo que ese sea el comportamiento previsto.

Barkmadley
fuente
8

Si miras la fuente aquí , será mucho más claro.

Esta función cumple las siguientes dos cosas:

  1. Sustituye los caracteres en la cadena de entrada con los definidos en JS_ESCAPE_MAP

    El propósito de esto es asegurarse de que el código JavaScript esté serializado correctamente sin interferir con la cadena externa dentro de la cual se está incrustando. Por ejemplo, si tiene una cadena de JavaScript entre comillas dobles, todas las comillas para los literales de cadena deben estar entre comillas simples para evitar que el código se rompa.

  2. La función también verifica si la cadena resultante es segura para html. Si no es así, realiza el escape necesario para asegurarse de que la cadena se convierta en html segura y devuelva el resultado.

Cuando usa escape_javascript, generalmente se incrusta dentro de otra cadena o html existente dinámicamente. Debes asegurarte de que hacer esto no hará que toda tu página no se procese.

Algunos aspectos de esta respuesta se señalaron en otras respuestas, pero quería reunir todos los elementos, incluida la diferencia entre el escape de JavaScript y el escape de HTML. Además, algunas respuestas aluden que esta función ayuda a evitar la inyección de script. No creo que ese sea el propósito de esta función. Por ejemplo, en su revisión si su revisión tiene alerta ('hola allí'), solo agregarlo al nodo no activará la ventana emergente. No lo está incrustando dentro de una función que se activa al cargar la página o mediante algún otro evento. Simplemente tener alerta ('hola') como parte de su html no significa que se ejecutará como javascript.

Dicho esto, no estoy negando que la inyección de script no sea posible. Pero para evitar eso, debe tomar medidas cuando tome los datos del usuario y los almacene en su base de datos. La función y el ejemplo que proporciona están relacionados con la representación de la información, que ya se guardó.

Espero que esto ayude y responda tu pregunta.

Tabrez
fuente