2012-09-09 27 views
18

¿Cómo puedo escapar de HTML con Jinja2 para que pueda usarse como una cadena en JavaScript (jQuery)?¿Cuerdas de escape para JavaScript usando Jinja2?

Si estuviera usando sistema de plantillas de Django podría escribir:

$("#mydiv").append("{{ html_string|escapejs }}"); 

de |escapejs filter escaparía cosas en html_string (por ejemplo, citas, caracteres especiales) que podrían romper el uso previsto de este bloque de código Django, pero Jinja2 hace no parece tener un filtro equivalente (¿me equivoco aquí?).

¿Existe una solución más limpia que copiar/pegar el código de Django?

+0

Ver aquí: http://jinja.pocoo.org/docs/templates/#escaping –

+0

No necesito escapar del texto de la etiqueta jinja en sí, necesita asegurarse de que 'html_string' no contenga ningún carácter dañino. – meshy

+0

Quizás el filtro seguro sea lo que buscas después de: http://flask.pocoo.org/docs/templating/#standard-filters –

Respuesta

7

Me enfrenté a un problema similar el año pasado. No estoy seguro de si está usando bottle, pero mi solución se veía más o menos así.

import json 

def escapejs(val): 
    return json.dumps(str(val)) # *but see [Important Note] below to be safe 

@app.route('/foo') 
def foo(): 
    return bottle.jinja2_template('foo', template_settings={'filters': {'escapejs': escapejs}}) 

(Envolví el dict template_settings en una función de ayuda que no uso en todas partes, pero lo mantuvo simple en este ejemplo.)

Por desgracia, no es tan simple como un filtro Jinja2 orden interna, pero Pude vivir feliz con eso, especialmente teniendo en cuenta que tenía varios otros filtros personalizados para agregar, también.

Nota importante: Punta de sombrero para @medmunds's por su astuto comentario a continuación, que nos recuerda que json.dumps no es seguro para XSS. IOW, no querrá usarlo en un servidor de producción orientado a Internet. La recomendación es escribir un safer json escape routine (o robar django's - lo siento OP, sé que esperabas evitar eso) y llamar a eso en lugar de usar json.dumps.

+0

¡Perfecto! No estoy usando bottle, estoy usando pywebkitgtk para construir una aplicación de escritorio, pero 'json.dumps' es exactamente lo que necesitaba. ¡Mucho más simple de lo que esperaba! ¡Gracias! – meshy

+0

¡Ah, y gracias por el enlace a la botella! No he visto eso antes, podría ser útil;) – meshy

+6

No creo que json.dumps() escape de todo lo que necesita preocuparse. Por ejemplo, como está escrito actualmente, 'escapejs (" ")' devuelve '" "' - que parece que podría permitir que una etiqueta de script de cierre (y cualquier elemento posterior a ella) se filtre en su html. (El filtro escapejs de Django hace escapes unicode en los caracteres < and >, lo que evita el problema.) – medmunds

-1

También puede usar jinja2's autoescape. Así, por ejemplo, se podría añadir a su entorno autoescape Jinja2 en Python:

JINJA_ENVIRONMENT = jinja2.Environment(
    loader=jinja2.FileSystemLoader(os.path.dirname(__file__)), 
    autoescape=True) 

Como alternativa, puede utilizar la extensión Autoescape añadido en Jinja 2.4 para tener más control sobre dónde se utiliza el autoescaping en el código HTML. Más información sobre este here y ejemplo (en Google App Engine) here.

Python:

JINJA_ENVIRONMENT = jinja2.Environment(
    loader=jinja2.FileSystemLoader(os.path.dirname(__file__)), 
    extensions=['jinja2.ext.autoescape']) 

HTML:

{% autoescape true %} 
    <html> 
     <body> 
      {{ IWillBeEscaped }} 
     </body> 
    </html> 
{% endautoescape %} 
+1

¿No es esto solo el escape estándar de HTML? La pregunta pregunta sobre Javascript? – pip

+1

No, eso definitivamente solo escapa HTML. –

11

Este es un filtro escapejs, basado en Django de uno, que escribí para su uso en las plantillas Jinja2:

_js_escapes = { 
     '\\': '\\u005C', 
     '\'': '\\u0027', 
     '"': '\\u0022', 
     '>': '\\u003E', 
     '<': '\\u003C', 
     '&': '\\u0026', 
     '=': '\\u003D', 
     '-': '\\u002D', 
     ';': '\\u003B', 
     u'\u2028': '\\u2028', 
     u'\u2029': '\\u2029' 
} 
# Escape every ASCII character with a value less than 32. 
_js_escapes.update(('%c' % z, '\\u%04X' % z) for z in xrange(32)) 
def jinja2_escapejs_filter(value): 
     retval = [] 
     for letter in value: 
       if _js_escapes.has_key(letter): 
         retval.append(_js_escapes[letter]) 
       else: 
         retval.append(letter) 

     return jinja2.Markup("".join(retval)) 
JINJA_ENVIRONMENT.filters['escapejs'] = jinja2_escapejs_filter 

Ejemplo uso seguro en una plantilla:

<script type="text/javascript"> 
<!-- 
var variableName = "{{ variableName | escapejs }}"; 
… 
//--> 
</script> 

Cuando variableName es str o unicode.

+0

Ya se requiere que '{{variableName | espacejs}} 'está entre comillas (simple o doble), por lo que los trucos de corchetes no son posibles. De lo contrario, incluso un espacio podría ser peligroso. – Tometzky

+2

Esta respuesta me ayudó en este hilo. Real mente doblador para escapar de los caracteres dentro de una cadena que se van a imprimir desde Python a HTML, que va a estar dentro de las etiquetas de cotización dentro de JavaScript que se analizará como JSON. Thnx por la ayuda! – Matthisk

2

simplemente he investigado este problema, mi solución es definir un filtro:

from flask import Flask, Markup 
app = Flask(__name__) 
app.jinja_env.filters['json'] = lambda v: Markup(json.dumps(v)) 

y en la plantilla:

<script> 
var myvar = {{myvar|json}} ; 
</script> 

Esto tiene la buena característica que mivar puede ser cualquier cosa que puede ser serializado por JSON

+4

No haga esto con contenido generado por el usuario, ya que los usuarios podrán ejecutar JS. Por ejemplo, cuando 'myvar' ='