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

问题描述 投票:0回答:2

看了文档,对mark_safe()的功能还是不太清楚。我想这与 CSRF 相关。但是为什么以及什么时候应该使用 mark_safe() 呢?

这是文档

mark_safe(s)

明确标记一个字符串对于 (HTML) 是安全的 输出目的。返回的对象可以在任何地方使用一个字符串 或 unicode 对象是合适的。

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

为了构建 HTML 片段,您通常应该使用 django.utils.html.format_html() 代替。

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

python django django-templates xss
2个回答
34
投票

Django 是一个框架,它默认尝试做“正确”的事情。这意味着当您做最简单的事情时,您可能正在做正确的事情。

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

PHP:

<? echo $foo ?>

可以给:

<script src="evil">

姜戈:

{{ foo }}

给出相同的输入:

&gt;script src="evil"&lt;

现在假设,您想放置一个链接

<a href="link">text</a>
。然后 django 将再次使用
&lt;&gt;
将其呈现为文本。如果您知道自己在做什么,您现在可以使用
mark_safe
来表示该文本是可信的(即不是来自用户输入)。

作为django程序员,通常你会在你的模板中使用

{{ foo|safe }}
{% autoescape off %}{{ foo }}{% endautoescape %}
,当字符串被声明为安全时更清楚。

那么,

mark_safe
用在哪里呢?当您编写自己的模板标签或过滤器时,您需要将字符串标记为对 python 安全,因为开发人员会假设,
{{ foo|mylinkifyfunction }}
做了正确的事情,即它转义了 url foo,但没有转义 HTML 代码
<a href=""></a>
网址周围。

一个示例实现可以是:

def mylinkifyfunction(url):
    escaped_url = escape_url(url) # Take care of escaping the URL in a safe way
    generated_html = f'<a href="{escaped_url}">{escaped_url}</a>' # This string could be dangerous, if it would use url instead of escaped_url
    return mark_safe(generated_html) # mark the string as safe, because it should be rendered as unescaped HTML

示例假设

escape_url
返回一个不包含HTML或
"
的字符串。


16
投票

还值得注意的是,在构建 HTML 代码片段时,建议使用

format_html(...)
函数而不是
mark_safe
并转义其所有参数。

所以,而不是写:

mark_safe("%s <b>%s</b> %s" % (
    some_html,
    escape(some_text),
    escape(some_other_text),
))

你应该改用:

format_html("{} <b>{}</b> {}",
    mark_safe(some_html),
    some_text,
    some_other_text,
)

这样做的好处是您无需对每个参数都应用

escape()
,如果您忘记了一个参数,则有出现错误和 XSS 漏洞的风险。

© www.soinside.com 2019 - 2024. All rights reserved.