2012-02-12 17 views
9

estoy usando la columna vertebral, y la forma general para pasar las colecciones cuando la carga de la página esEscapar</script> etiqueta dentro Javascript

window.router = new Routers.ManageRouter({store: #{@store.to_json}); 

que está muy bien y funciona bien, hasta que alguien decide añadir el texto "<script>alert("owned")</script> "a uno de los campos de la tienda. el último </script> obviamente cierra el javascript. ¿Cómo se puede evitar esto?

:javascript 
    $(function() { 
     window.router = new Dotz.Routers.ManageRouter({store: #{@store.to_json}}); 
     Backbone.history.start(); 
    }); 

Las salidas anteriores:

<script> 
    //<![CDATA[ 
     $(function() { 
     window.router = new Dotz.Routers.ManageRouter({store: '{"_id":"4f3300e19c2ee41d9a00001c", "points_text":"<script>alert(\"hey\");</script>"'}); 
     Backbone.history.start(); 
     }); 
    //]]> 
    </script> 

Respuesta

14

dentro de un bloque <script> es syntactically illegal tener ningún </ seguido de un nombre, no sólo </script> -así que debe escapar en cualquier lugar donde aparezca. Por ejemplo:

:javascript 
    var foo = { store: #{@store.to_json.gsub('</','<\/')} }; 

Esto creará la secuencia <\/ dentro de sus cadenas JS, que se interpreta a ser el mismo que </. Asegúrese de usar comillas simples en su cadena de reemplazo gsub, o bien use gsub("</", "<\\/") debido a la diferencia entre comillas simples y dobles en Ruby.

Se muestra en acción:

irb:02.0> s = "<b>foo</b>" # Here's a dangerous string 
#=> "<b>foo</b>" 

irb:03.0> a = [s]   # Wrapped in an array, for fun. 
#=> ["<b>foo</b>"] 

irb:04.0> json = a.to_json.gsub('</', '<\/') # Sanitized 
irb:05.0> puts json  # This is what would come out in your HTML; safe! 
#=> ["<b>foo<\/b>"] 

irb:06.0> puts JSON.parse(json).first # Same as the original? Yes! Yay! 
#=> <b>foo</b> 

Si está utilizando rieles (o ActiveSupport) puede activar JSON escaping:

ActiveSupport::JSON::Encoding.escape_html_entities_in_json = true 

visto en acción:

irb:02.0> a = ["<b>foo</b>"] 
irb:03.0> puts a.to_json # Without the magic 
#=> ["<b>foo</b>"] 

irb:04.0> require 'active_support' 
irb:05.0> ActiveSupport::JSON::Encoding.escape_html_entities_in_json = true 
irb:06.0> puts a.to_json # With the magic 
#=> ["\u003Cb\u003Efoo\u003C/b\u003E"] 

Produce JSON eso es más detallado de lo que necesita para resolver este problema en particular, pero es efectivo.

-1

se le olvidó la ''

:javascript 
    $(function() { 
     window.router = new Dotz.Routers.ManageRouter({store: '#{@store.to_json}'}); 
     Backbone.history.start(); 
    }); 
+0

pues no. todavía se renderizará algo como '{id: '324234', texto: '' ...' mientras se cierra el script – CamelCamelCamel

+0

¿puedes publicar el HTML de la página renderizada, por favor? – Blacksad

+0

actualizó la pregunta. – CamelCamelCamel

4

La palabra mágica es:

ActiveSupport.escape_html_entities_in_json = true 

Aunque marcado como obsoleto, esto todavía funciona en las versiones actuales carriles (ver mi rails c):

ruby-1.9.3-head :001 > ::Rails.version 
=> "3.2.1" 
ruby-1.9.3-head :002 > ["<>"].to_json 
=> "[\"<>\"]" 
ruby-1.9.3-head :003 > ActiveSupport.escape_html_entities_in_json = true 
=> true 
ruby-1.9.3-head :004 > ["<>"].to_json 
=> "[\"\\u003C\\u003E\"]" 
+0

Este formulario fue [descontinuado en Rails v2.3.3 +] (http://apidock.com/rails/ActiveSupport/escape_html_entities_in_json%3D/class) – Phrogz

+0

Funcionó en mi consola de 3.1.something rails. – iblue

+0

Impar; quizás ellos o usted tienen una compatibilidad retroactiva. No funciona en Raw ActiveSupport v3.0.7; no obstante, eliminaré mi voto negativo sobre tu palabra de que funciona. – Phrogz

Cuestiones relacionadas