Django在很大程度上可以规避许多风险,但这并不说明使用Django就可以万无一失,要想让你的网站能够安稳运行,了解Django的安全特性非常重要,你要首先知道,在哪些方面Django提供了保护机制,而哪些地方Django做的还不太完善。
一、跨站点脚本(XSS)攻击保护
我们知道,Django的模板系统可以生成任何text-based格式,例如HTML。
设想这样一种情况:
Hello,{{ username }}!
乍一看这行代码似乎没什么问题,但是想一想,如果用户把自己的名字设置成 <b>username
这种形式会怎么样?
那么这行代码在渲染后的就会变成:
Hello,<b>username!
这将导致这行代码之后的所有HTML文本都会被加粗显示!
显然,不应该盲目的相信用户提交的所有数据并把它们直接使用在你的网页中,因为恶意用户可以利用这种漏洞干坏事,这种风险的安全漏洞就被称为 跨站点脚本(XSS)攻击
。
有两种方式来避免这个风险:
- 第一种是使用
escape
过滤器,它会将潜在的有危害的HTML字符转换称无害的HTML字符,最初Django把这种办法作为默认解决方案,但这无疑会加重开发人员的负担,因为你要确保所有可能有危险的地方都加上了escape过滤器。 - 第二,你可以使用Django的默认自动HTML转义,它会将危害的HTML字符自动转义为无害HTML字符,转义策略如下:
< --> <
> --> >
' (single quote) --> '
" (double quote) --> "
& --> &
这种自动转义行为是Django默认的,只要你使用Django的模板系统,这种转义就会运行。
需要注意的是,并不能说采用了这种方法就可以高枕无忧,事实上,如果采用以下这种方式,那么自动转义将失效:
<style class={{ var }}>...</style>
如果不希望数据自动转义,那么也有以下几种方式可供选择(这种情况也是很常见的,比如你想要在你的页面中的某些部分使用原生的HTML,这可能是用户的评论,或者一些其它的地方):
对于单个变量,可以使用safe过滤器
:
This will be escaped: {{ data }}
This will not be escaped: {{ data|safe }}
对于模板块,可以使用autoescape标签
:
{% autoescape off %}
Hello {{ name }}
{% endautoescape %}
该标签有两个可选参数,off
和on
,其中off会关闭自动转义,on会开启自动转义。
另外,该标签具有传递性,如果它的父模板开启了自动转义,那么任何extends和include它的模板也将开启自动转义。
如下:
#base.html
{% autoescape off %}
<h1>{% block title %}{% endblock %}</h1>
{% block content %}
{% endblock %}
{% endautoescape %}
#child.html
{% extends "base.html" %}
{% block title %}This & that{% endblock %}
{% block content %}{{ greeting }}{% endblock %}
除了上述的这些,django.utils的一些模板也提供了类似的功能,如 :django.utils.safestring
。
class : SafeString
:该类是str的子类,该类的实例被用于模板系统中,则表明该字符串是一个安全字符串,不应该再被转义。
make_safe(s)
:显式的将字符串标记为安全字符串,即返回SafeString。可以在单个字符串上多次调用,也可以用作装饰器。但是需要注意的是,一旦SafeString的值被更改,那么它将失去 safe 的特性。
如:
>>> mystr = '<b>Hello World</b> '
>>> mystr = mark_safe(mystr)
>>> type(mystr)
<class 'django.utils.safestring.SafeString'>
>>> mystr = mystr.strip() # removing whitespace
>>> type(mystr)
<type 'str'>
综上,因为Django的自动转义并不是万无一失,因此在使用以上这些方法,包括:
- escape
- automatic HTML escaping
- safe
- autoescape(tag)
- make_safe()
等这些标签、过滤器或方法时,务必要格外注意。
此外,在数据库中存储HTML时,特别是在检索和显示HTML时,也应该非常小心。