为什么以及何时使用Django mark_safe()函数

day*_*day 13 django django-templates

阅读文档后,mark_safe()似乎仍然是一个神话.我想这与CSRF有关.但是为什么以及何时使用mark_safe()?

这是文档

mark_safe(S)[来源]

将字符串明确标记为(HTML)输出目的是安全的.返回的对象可以在字符串或unicode对象适当的任何地方使用.

可以在单个字符串上多次调用.

要构建HTML片段,通常应该使用django.utils.html.format_html().

如果修改,标记为安全的字符串将再次变得不安全 例如:

all*_*llo 20

Django是一个框架,它试图默认做"正确"的事情.这意味着当你做最简单的事情时,你可以做出正确的事情.

现在让我们看一下php和python中的一些模板:

PHP:

<? echo $foo ?>
Run Code Online (Sandbox Code Playgroud)

可以给:

<script src="evil">
Run Code Online (Sandbox Code Playgroud)

Django的:

{{ foo }}
Run Code Online (Sandbox Code Playgroud)

给出相同的输入:

&gt;script src="evil"&lt;
Run Code Online (Sandbox Code Playgroud)

现在假设您要放置一个链接<a href="link">text</a>.然后django将&lt;&gt;再次使用它作为文本.如果您知道自己在做什么,现在可以mark_safe用来表示文本是可信的(即不是来自userinput).

通常,您将在模板中使用{{ foo|safe }}{% autoescape off %}{{ foo }}{% endautoescape %}作为django编程器,当字符串被声明为安全时更清楚.

那么,在哪里mark_safe使用?当你编写自己的模板标签或过滤器时,你需要将字符串标记为python安全,因为开发人员会认为{{foo | mylinkifyfunction}}做了正确的事(即它逃脱了网址foo,但是没有逃脱在<a href=""></a>周围的URL).

  • mark_safe 告诉 django 模板应该从 Python 代码中按原样使用字符串。通常这不是您想要的。这是一个[示例](https://github.com/django/django/blob/222d0633010e2f37f9fbd2d0559ecc4a5643c738/django/template/defaultfilters.py#L481),其中python代码应该为模板输出``&lt;br /&gt;``,这是没有逃脱的。 (2认同)

rad*_*doh 7

还值得注意的是,在构建 HTML 代码片段时,建议使用format_html(...)function 而不是mark_safe并转义其所有参数。

所以,而不是写:

mark_safe("%s <b>%s</b> %s" % (
    some_html,
    escape(some_text),
    escape(some_other_text),
))
Run Code Online (Sandbox Code Playgroud)

你应该使用:

format_html("{} <b>{}</b> {}",
    mark_safe(some_html),
    some_text,
    some_other_text,
)
Run Code Online (Sandbox Code Playgroud)

这样做的好处是你不需要应用escape()到每个参数,如果你忘记了一个错误和 XSS 漏洞的风险。