首先想說的是它的安全性,這方面確實能讓我感受到它的良苦用心。這主要可以分為兩點:
一、防范跨站偽造請求(Cross-site request forgery,簡稱 CSRF 或 XSRF)
CSRF 的意思簡單來說就是,攻擊者偽造真實用戶來發(fā)送請求。
舉例來說,假設(shè)某個銀行網(wǎng)站有這樣的 URL:
http://bank.example.com/withdraw?amount=1000000&for=Eve
當(dāng)這個銀行網(wǎng)站的用戶訪問該 URL 時,就會給 Eve 這名用戶一百萬元。用戶當(dāng)然不會輕易地點擊這個 URL,但是攻擊者可以在其他網(wǎng)站上嵌入一張偽造的圖片,將圖片地址設(shè)為該 URL:
<img src="http://bank.example.com/withdraw?amount=1000000&for=Eve">
那么當(dāng)用戶訪問那個惡意網(wǎng)站時,瀏覽器就會對該 URL 發(fā)起一個 GET 請求,于是在用戶毫不知情的情況下,一百萬就被轉(zhuǎn)走了。
要防范上述攻擊很簡單,不允許通過 GET 請求來執(zhí)行更改操作(例如轉(zhuǎn)賬)即可。不過其他類型的請求照樣也不安全,假如攻擊者構(gòu)造這樣一個表單:
代碼如下:<form action="http://bank.example.com/withdraw" method="post">
<p>轉(zhuǎn)發(fā)抽獎送 iPad 啊!</p>
<input type="hidden" name="amount" value="1000000">
<input type="hidden" name="for" value="Eve">
<input type="submit" value="轉(zhuǎn)發(fā)">
</form>
不明真相的用戶點了下“轉(zhuǎn)發(fā)”按鈕,結(jié)果錢就被轉(zhuǎn)走了…
要杜絕這種情況,就需要在非 GET 請求時添加一個攻擊者無法偽造的字段,處理請求時驗證這個字段是否修改過。
Tornado 的處理方法很簡單,在請求中增加了一個隨機生成的 _xsrf 字段,并且 cookie 中也增加這個字段,在接收請求時,比較這 2 個字段的值。
由于非本站的網(wǎng)頁是不能獲取或修改 cookie 的,這就保證了 _xsrf 無法被第三方網(wǎng)站偽造(HTTP 嗅探例外)。
當(dāng)然,用戶自己是可以隨意獲取和修改 cookie 的,不過這已經(jīng)不屬于 CSRF 的范疇了:用戶自己偽造自己所做的事情,當(dāng)然由他自己來承擔(dān)。
要使用該功能的話,需要在生成 tornado.web.Application 對象時,加上 xsrf_cookies=True 參數(shù),這會給用戶生成一個名為 _xsrf 的 cookie 字段。
此外還需要你在非 GET 請求的表單里加上 xsrf_form_html(),如果不用 Tornado 的模板的話,在 tornado.web.RequestHandler 內(nèi)部可以用 self.xsrf_form_html() 來生成。
對于 AJAX 請求來說,基本上是不需要擔(dān)心跨站的,所以 Tornado 1.1.1 以前的版本并不對帶有 X-Requested-With: XMLHTTPRequest 的請求做驗證。
后來 Google 的工程師指出,惡意的瀏覽器插件可以偽造跨域 AJAX 請求,所以也應(yīng)該進(jìn)行驗證。對此我不置可否,因為瀏覽器插件的權(quán)限可以非常大,偽造 cookie 或是直接提交表單都行。
新聞熱點
疑難解答
圖片精選