如何防止 Django 基本内联自动转义

Posted

技术标签:

【中文标题】如何防止 Django 基本内联自动转义【英文标题】:How to prevent Django basic inlines from autoescaping 【发布时间】:2012-04-13 22:02:53 【问题描述】:

Django Basic Inlines 应用程序根据 app/model/id 组合从伪 html 语法呈现预先确定的模板。例如,如果您正在撰写博客文章,则可以插入保存在图像模型中的图像:

# In the admin
This is the body of my post.

<inline type="media.image" id="1" class="full">

模板然后采用render_inlines过滤器,需要标记safe才能正确呈现HTML:

# Template
 post.body|render_inlines|safe 

但即使使用safe,过滤器仍会转义HTML,在源代码中创建&amp;lt;p&amp;gt;&amp;lt;img src="..."&amp;gt;&amp;lt;p&amp;gt;

根据文档,过滤器应使用mark_safe 以防止在过滤器级别自动转义,但parser.py 中的inlines 函数已使用mark_safe

在 Django 1.4 中是否需要进一步停止自定义过滤器层的自动转义?我似乎无法摆脱这种自动转义,无论是在

inlines function 或 render_inlines function.

我尝试使用autoescape=None,但似乎也没有帮助。

【问题讨论】:

去掉 safe 和 % autoescape off % 的结果是什么? 没什么,同样的结果,这就是为什么我相信转义发生在过滤器级别而不是模板。如果某些内容已经被转义,则在模板中放置safe 或关闭autoescape 不会执行任何操作。已经很安全了。 【参考方案1】:

对此的另一个解决方案是将新代码转换为 BeautifulSoup 对象,并用该对象替换。这样漂亮的汤似乎表现得很好。

这会给你转义的 html:

soup = BeautifulSoup(html_doc)
body = soup.body
new_html = """<p> this is some deap code</p><a href="#">Pointless even</a>"""
body.replaceWith(new_html)

这使您的 html 未转义:

soup = BeautifulSoup(html_doc)
body = soup.body
new_html = """<p> this is some deap code</p><a href="#">Pointless even</a>"""
body.replaceWith(BeautifulSoup(new_html))

【讨论】:

【参考方案2】:

我维护 Inline 应用程序的 a fork。 Richard 就这个问题联系了我,我可以追溯到 BeautifulSoup,而不是 Django。

问题在于 BeautifulSoup 的 replaceWith() 方法被用来用渲染的模板替换内联标记。 render_to_string() 的结果当然是一个字符串。当replaceWith() 接收到一个字符串时,它会将其转换为NavigableString。由于 BeautifulSoup 期望 NavigbleStrings 是字符串,它假定它们是不安全的并转义任何 HTML 字符。结果是 Inline 的 inlines() 函数返回的值包含一堆 &amp;gt;&amp;lt; 而不是 &lt;&gt;

我在 Django 1.3 中没有注意到这个问题。当我查看时,BeautifulSoup 确实返回了转义的 HTML。 Django 的|safe 模板过滤器一定已经对之前转义的HTML 进行了转义。在 Django 1.4 中,它不再这样做了。 (它不应该那样做!)

我的解决方法是使用 BeautifulSoup 解析传入的值,并使用 BeautifulSoup 来查找所有内联标记,就像以前一样。而不是使用 BeautifulSoup 的 replaceWith() 方法将内联标记替换为呈现的内联模板,我现在只使用 Python 的普通旧 str.replace()。我觉得有点蹩脚,将解析后的汤转换回字符串,然后进行字符串替换。但它有效。我部分想完全取消 BeautifulSoup 并使用正则表达式找到内联标记,但 we all know how that ends。如果有人有更好的主意,我会全力以赴!

修复最初是在 this commit 中实现的。我在下面的提交中改进了它,但显然 *** 只允许我发布最多两个链接,所以你必须自己找到那个!

【讨论】:

Django 的 |safe 从未进行过“转义”,它只是简单地将文本标记为不需要进一步转义。【参考方案3】:

这是因为 render_to_string here。转到inlines/app_model.htmlinlines/default.html 并在内容变量之后添加|safe

【讨论】:

您的意思是 app/templates/app/model_detail.html 和 app/templates/inlines/default.html,对吗?标记那些safe?这就是我已经在做的事情。有人在帮助我,这可能是 BeautifulSoup 3.2.0 与 BeautifulSoup 3.2.1 的问题,以及您引用的行中 replaceWith 的更改方式。 不是model_detail.html,而是该行使用的模板。您可以使用print 或 pdb 来检查它。在该行上,您的数据被渲染到模板中,然后在您调用内联的地方返回结果。您应该在外部和内部模板中禁用自动转义。

以上是关于如何防止 Django 基本内联自动转义的主要内容,如果未能解决你的问题,请参考以下文章

防止 django 管理员转义 html

Emacs:防止自动填充模式在乳胶 \text... 内联命令中断行

vue内容都会被自动转义,所以防止了脚本注入吗?

08-Django模板

如何防止 SQL 注入转义字符串

php如何防止sql注入