9

我想向用户显示一些文本。我发送的字符串变量有多个换行符,我不想\n显示。所以我做了:

footext = """f
o
o"""

#footext == "f\no\no"

@app.route("/someurl")
def foo():
    return render_template("bar.html", text = footext.replace("\n", "<br />"))

bar.html:

<html>
{{ text }}
</html>

但是启用了自动转义,我看到的是f<br />o<br />o. 我的方法也不安全,我希望每个标签都<br />从文本中转义。我看了一下flask.Markup 模块,但是它们也没有真正起作用。

这样做的正确方法是什么?

4

3 回答 3

9

您可以采取两种合理的方法。

解决方案 1

当您将不安全的输入与 HTML 组合到一个变量flask.Markup中时,实际上是一种非常方便的方法。<br />基本思想是将文本拆分为换行符,确保 HTML 转义您不信任的每一行,然后通过您信任的标签将它们粘合在一起。

这是演示这一点的完整应用程序。它使用与bar.html您的问题相同的模板。请注意,我在 中添加了一些不安全的 HTML,footext以演示为什么关闭自动转义不是解决您的问题的安全解决方案。

import flask

app = flask.Flask(__name__)

footext = """f
o
<script>alert('oops')</script>
o"""


@app.route("/foo")
def foo():
    text = ""
    for line in footext.split('\n'):
        text += flask.Markup.escape(line) + flask.Markup('<br />')
    return flask.render_template("bar.html", text=text)

if __name__ == "__main__":
    app.run(debug=True)

解决方案 2

另一种选择是将复杂性推入您的模板中,从而为您提供更简单的视图。只需分成footext几行,然后您可以在模板中循环它,自动转义将负责保持此安全。

更简单的视图:

@app.route("/foo")
def foo():
    return flask.render_template("bar.html", text=footext.split('\n'))

模板 bar.html 变为:

<html>
    {%- for line in text -%}
        {{ line }}
        {%- if not loop.last -%}
            <br />
        {%- endif -%}
    {%- endfor -%}
</html>

结论

我个人更喜欢解决方案 2,因为它将渲染问题(行由<br />标签分隔)放在它们所属的模板中。如果您以后想更改它,例如,在项目符号列表中显示行,您只需要更改您的模板,而不是您的代码。

于 2013-01-29T23:31:49.240 回答
6

我将把我之前的答案作为一个例子。

这种事情的一个很好的解决方案是自定义过滤器,它可以让您使用诸如

{{ block_of_text | nl2br }}

您可以方便地使用nl2br过滤器片段(或轻松自定义)!

于 2013-01-30T02:53:02.793 回答
1

在 Jinja2 模板中关闭自动转义,或使用原始块

于 2013-01-29T21:46:32.630 回答