2012-09-09 87 views
18

如何使用Jinja2转义HTML,以便它可以在JavaScript(jQuery)中用作字符串?使用Jinja2逃避JavaScript的字符串?

如果我使用Django的模板系统,我可以写:

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

Django的|escapejs filter会逃避html_string东西(如引号,特殊字符),可以打破打算使用此代码块,但Jinja2的呢似乎没有一个等效的过滤器(我在这里错了吗?)。

是否有比从Django复制/粘贴代码更清洁的解决方案?

+0

请看这里:http://jinja.pocoo.org/docs/templates/#escaping –

+0

我不需要逃避jinja标签文本本身,我需要确保'html_string'不包含任何有害字符。 – meshy

+0

也许|安全过滤器是你以后比:http://flask.pocoo.org/docs/templating/#standard-filters –

回答

7

去年我遇到过类似的问题。不知道您是否使用bottle,但我的解决方案看起来像这样。

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}}) 

(我包裹template_settings字典中的一个辅助功能,因为我用它无处不在,但我一直是在这个例子中简单的。)

不幸的是,它不是一个内置的Jinja2过滤器一样简单,但我能够愉快地生活 - 特别是考虑到我还有其他几个自定义过滤器。

重要注意事项:由于他在下面的精明评论中提到了@ medmunds's的帽子,提醒我们json.dumps不是XSS安全的。 IOW,你不想在面向互联网的生产服务器上使用它。建议写一个safer json escape routine(或者窃取django的 - 对不起OP,我知道你希望避免这种情况)并且调用它而不是使用json.dumps。

+0

完美!我没有使用瓶子,我使用pywebkitgtk来构建桌面应用程序,但是“json.dumps”正是我所需要的。比我希望的简单得多!谢谢! – meshy

+0

哦,谢谢你的链接到瓶!我以前没有见过,可以派上用场;) – meshy

+6

我不认为json.dumps()可以逃脱你需要担心的一切。例如,正如目前所写,'escapejs(“”)'返回''“' - 这看起来好像它可以允许关闭脚本标记(以及任何之后的任何东西!)泄漏到你的html中。 (Django的escapejs过滤器在< and >字符上做了unicode转义,这就避免了这个问题。) – medmunds

-1

您也可以使用jinja2的autoescape。所以,举例来说,你可以在Python添加autoescape到您的Jinja2环境:

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

或者,你可以使用Autoescape扩展在神社2.4加入到有超过其中autoescaping在HTML中使用更多的控制。有关此here和示例(在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

这不就是标准的HTML转义吗?问题关于Javascript问题? – pip

+1

不,绝对只是HTML转义。 –

11

这是一个escapejs过滤器,基于Django的一个,我在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 

例模板中的安全使用:

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

当variableName是strunicode

+0

已经要求'{{variableName | ''是用引号(单或双),所以方括号的技巧是不可能的。否则,即使是空间也可能是危险的。 – Tometzky

+2

这个答案帮我解决了这个问题。真正的思想弯曲者转义将要从Python打印到HTML的字符串内的字符,该字符串将在JavaScript内部的将被解析为JSON的引号标签内。 thnx的帮助! – Matthisk

2

我研究这个问题,我的解决方法是定义过滤器:

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

,并在模板:

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

这具有很好的功能是MYVAR可以是任何可以JSON序列化

+4

不要对用户生成的内容进行此操作,因为用户将能够执行JS。例如,当'myvar' ='