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