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時,也應該非常小心。