含義
CSRF(Cross-site request forgery),中文名稱:跨站請求僞造,也被稱爲:one click attack/session riding,縮寫爲:CSRF/XSRF。
解釋
這幅圖非常形象的解釋了CSRF原理的具體過程。
從上圖可以看出,要完成一次CSRF攻擊,受害者必須依次完成兩個步驟:
- 登錄受信任網站A,並在本地生成Cookie。
- 在不登出A的情況下,訪問危險網站B。
看到這裏,你也許會說:“如果我不滿足以上兩個條件中的一個,我就不會受到CSRF的攻擊”。是的,確實如此,但你不能保證以下情況不會發生:
-
你不能保證你登錄了一個網站後,不再打開一個tab頁面並訪問另外的網站。
-
你不能保證你關閉瀏覽器了後,你本地的Cookie立刻過期,你上次的會話已經結束。(事實上,關閉瀏覽器不能結束一個會話,但大多數人都會錯誤的認爲關閉瀏覽器就等於退出登錄/結束會話了…)
-
上圖中所謂的攻擊網站,可能是一個存在其他漏洞的可信任的經常被人訪問的網站。
flask 中的CSRF保護
Flask-WTF 表單保護你免受 CSRF 威脅,你不需要有任何擔心。儘管如此,如果你有不包含表單的視圖,那麼它們仍需要額外的保護。
例如,由 AJAX 發送的 POST 請求,並沒有通過表單。在 0.9.0 之前版本,你無法獲得 CSRF 令牌。這就是爲什麼我們編寫了 CSRF 模塊。
實現
要對所有視圖函數啓用 CSRF 保護,你需要啓用 CsrfProtect 模塊:
from flask_wtf.csrf import CsrfProtect
CsrfProtect(app)
與任何其它的 Flask 擴展一樣,你可以惰性加載它:
from flask_wtf.csrf import CsrfProtect
csrf = CsrfProtect()
def create_app():
app = Flask(__name__)
csrf.init_app(app)
如果模板中有表單,你不需要做任何事。與之前一樣:
<form method="post" action="/">
{{ form.csrf_token }}
</form>
但如果模板中沒有表單,你仍需要 CSRF 令牌:
<form method="post" action="/">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
</form>
無論何時未通過 CSRF 驗證,都會返回 400 響應。你可以自定義這個錯誤響應:
@csrf.error_handler
def csrf_error(reason):
return render_template('csrf_error.html', reason=reason), 400
我們強烈建議你對所有視圖啓用 CSRF 保護。但也提供了將某些視圖函數除外的途徑:
@csrf.exempt
@app.route('/foo', methods=('GET', 'POST'))
def my_handler():
# ...
return 'ok'
參考
https://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html
http://docs.jinkan.org/docs/flask-wtf/csrf.html