做Web開發的人都明白,我們應該避免在用戶輸入信息中出現HTML標籤。比如考慮下面的Django模板信息:
Hello {{ name }}.
這看起來沒什麼問題,但是假如用戶輸入的name是下面這樣的信息就麻煩了:
<script type="text/javascript">// <![CDATA[
alert(’hello’)
// ]]></script>
瀏覽器會解析這個信息並彈出一個對話框,這顯然不是我們所希望的。毫無疑問,對於用戶輸入的信息,我們總是應該進行驗證。你不知道是否會有一個“惡意”的用戶會利用這個漏洞來做一些不好的事情。
爲了避免以上問題,你有兩個選擇:
1. 給每個變量加上一個escape過濾器來進行HTML轉義。Django剛發佈那幾年都是這樣要求開發人員的。但是,這相當於把責任踢給了開發人員。難免會有人忘記了寫這個轉義過濾器。
2. 或者你可以選擇使用Django的自動HTML轉義功能,下面我將介紹它。
缺省情況下的轉義方式是這樣的:
• < 被轉換爲 <
• > 被轉換爲 >
• ’ (單引號)被轉換爲 '
• ” (雙引號)被轉換爲 "
• & 被轉換爲 &
上面的轉義規則是缺省的,所以如果你不想讓某段信息被執行HTML轉義,可以這樣:
1. 對於單個變量,可以在其後面加上safe過濾器,告訴Django這個字符串不用進行HTML轉義。比如:
This will be escaped: {{ data }}
This will not be escaped: {{ data|safe }}
如果其中的data的值是 <b> 上面兩行的最終輸出結果爲:
This will be escaped: <b>
This will not be escaped: <b>
2. 對於一段模板內容可以使用autoescape標籤,比如:
{% autoescape off %}
Hello {{ name }}
{% endautoescape %}
這裏的off 參數表明被autoescape包含的信息都不需要執行HTML轉義。on 參數表示需要執行HTML轉義,比如有的時候你希望一段信息中大部分不需要HTML轉義,但是其中某個部分需要HTML轉義,可以這樣:
{% autoescape off %}
This will not be auto-escaped: {{ data }}.
Nor this: {{ other_data }}
{% autoescape on %}
Auto-escaping applies again: {{ name }}
{% endautoescape %}
{% endautoescape %}
另外需要注意的一點是autoescape是存在繼承性的,比如你在父模板中有一個autoescape標籤並且參數爲off,那麼繼承它的子模板也會在相應的部分繼承這一特性。比如:
# 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 %}
最後要提一下 字符串的default過濾器,比如下面這個例子:
{{ data|default:"This is a string literal." }}
如果你在default:後面的缺省值中包含了HTML特殊字符,那麼是不會被轉義的,比如你應該按照下面第一種的方式來寫,而不是第二種:
# 正確的寫法
{{ data|default:"3 < 2" }}
# 錯誤的寫法
{{ data|default:"3 < 2" }}