flask——CSRFToken保護

flask總結05(在 Flask 項目中解決 CSRF 攻擊)

 

一:安裝 flask_wtf

pip install flask_wtf

二:設置應用程序的 secret_key,用於加密生成的 csrf_token 的值

# session加密的時候已經配置過了.若是沒有在配置項中設置,則以下:
app.secret_key = "#此處能夠寫隨機字符串#"

三:導入 flask_wtf.csrf 中的 CSRFProtect 類,進行初始化,並在初始化的時候關聯 app

from flask.ext.wtf import CSRFProtect
CSRFProtect(app)

四:在表單中使用 CSRF 令牌:

<form method="post" action="/">
    <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
</form>

 

五:scrf的過程理解

代碼顯示方法不被容許的代碼html

#manage.py前端

from flask import Flask, render_template, request, g
from settings.dev import DevConfig
from flask.ext.wtf import CSRFProtect

app = Flask(__name__, template_folder="templates", static_folder="static")
app.config.from_object(DevConfig)

CSRFProtect(app)

# @app.route("/csrf_test", methods=["get", "post"])
@app.route("/csrf_test")
def index():
    if request.method == "GET":
        return render_template("form.html")

    else:
        print(request.form)

        return "ok"

if __name__ == "__main__":
    app.run()

templates下的form.htmlweb

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>csrf案例</title>
</head>
<body>
    <form action="" method="post">
        帳號:<input type="text" name="username"><br><br>
        密碼:<input type="password" name="password"><br><br>
        <input type="submit" value="提交">
    </form>
</body>
</html>

運行後顯示的結果是:ajax

而後修改manage.py中的代碼,添加json

@app.route("/csrf_test", methods=["get", "post"])

代碼以下:flask

from flask import Flask, render_template, request, g
from settings.dev import DevConfig
from flask.ext.wtf import CSRFProtect

app = Flask(__name__, template_folder="templates", static_folder="static")
app.config.from_object(DevConfig)

CSRFProtect(app)

@app.route("/csrf_test", methods=["get", "post"])
def index():
    if request.method == "GET":
        return render_template("form.html")

    else:
        print(request.form)

        return "ok"

if __name__ == "__main__":
    app.run()

再次執行:而且提交:後端

說明須要在html文檔中添加:csrf_token瀏覽器

<input type="hidden" name="csrf_token" value="{{csrf_token()}}">

修改後的代碼是:cookie

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>csrf案例</title>
</head>
<body>
    <form action="" method="post">
        <input type="hidden" name="csrf_token" value="{{csrf_token()}}">
        帳號:<input type="text" name="username"><br><br>
        密碼:<input type="password" name="password"><br><br>
        <input type="submit" value="提交">
    </form>
</body>
</html>

運行後的結果顯示:session

 

flask——CSRFToken保護

根據 csrf_token 校驗原理,具體操做步驟有如下幾步:

1.後端生成 csrf_token 的值,在前端請求登陸或者註冊界面的時候將值傳給前端,傳給前端的方式可能有如下兩種:
在模板中的 From 表單中添加隱藏字段
將 csrf_token 使用 cookie 的方式傳給前端
2.在前端發起請求時,在表單或者在請求頭中帶上指定的 csrf_token
3.後端在接受到請求以後,取到前端發送過來的 csrf_token,與第1步生成的 csrf_token 的值進行校驗
4.若是校驗對 csrf_token 一致,則表明是正常的請求,不然多是僞造請求,不予經過

而在 Flask 中,CSRFProtect 這個類專門只對指定 app 進行 csrf_token 校驗操做,因此開發者須要作如下幾件事情:
生成 csrf_token 的值
將 csrf_token 的值傳給前端瀏覽器
在前端請求時帶上 csrf_token 值

生成 csrf_token 的值

# 導入生成 csrf_token 值的函數
from flask_wtf.csrf import generate_csrf
# 調用函數生成 csrf_token
csrf_token = generate_csrf()

將 csrf_token 的值傳給前端瀏覽器
實現思路:能夠在請求勾子函數中完成此邏輯

@app.after_request
def after_request(response):
    # 調用函數生成 csrf_token
    csrf_token = generate_csrf()
    # 經過 cookie 將值傳給前端
    response.set_cookie("csrf_token", csrf_token)
    return response

在前端請求時帶上 csrf_token 值
根據登陸和註冊的業務邏輯,當前採用的是 ajax 請求
因此在提交登陸或者註冊請求時,須要在請求頭中添加 X-CSRFToken 的鍵值對

$.ajax({
    url:"/passport/register",
    type: "post",
    headers: {
        "X-CSRFToken": getCookie("csrf_token")#get_Cookie爲自定義函數
    },
    data: JSON.stringify(params),
    contentType: "application/json",
    success: function (resp) {
        if (resp.errno == "0"){
            // 刷新當前界面
        location.reload()
        }else {
            $("#register-password-err").html(resp.errmsg)
            $("#register-password-err").show()
        }
    }
})

 

flask csrf保護的使用技巧

CSRF(Cross-site request forgery)跨站請求僞造,也被稱爲「One Click Attack」或者Session Riding,一般縮寫爲CSRF或者XSRF,是一種對網站的惡意利用。 ——百度百科

網上關於csrf攻擊的一個最典型的例子是銀行經過url+參數轉錢的問題,很好理解。

flask 做爲一個強帶的web微框架,天然也是支持防範csrf攻擊的。

經過Flask-WTF來保護表單免受CSRF攻擊
何爲Flask-WTF
簡單說來,使用它能夠方便咱們構建表單和驗證表單,具體用法這裏不作贅述

怎麼開啓保護?
極少的配置,一個應用令牌:

app.config['SECRET_KEY'] = 'you can't know'
或csrf專用令牌
app.config['WTF_CSRF_SECRET_KEY'] = 'IT 666 to 709 kill pic'

Flask-WTF默認是開啓CSRF保護的,你須要的作的是在你的模板中表單一欄加入:

{{ form.csrf_token }}
或者
{{ form.hidden_tag() }}

這樣,csrf保護已經開啓。如若你沒有上面的代碼,提交表單會沒法經過form.validate_on_submit(),錯誤爲

{'csrf_token': ['The CSRF token is missing.']},但這並不會致使http錯誤,僅是沒法經過驗證。

關閉保護
天然,咱們極可能有的表單不須要保護,那麼,如下三種:

全局禁用:app.config中設置WTF_CSRF_ENABLED = False
單個表單禁用:生成表單時加入參數form = Form(csrf_enabled=False)
不使用Flask-WTF…啊啊,這個很好理解

http://docs.jinkan.org/docs/flask-wtf/from.html

flask 內置的保護機制

有些時候,我根本就用不到Flask-WTF,那麼我可使用flask自身提供的保護機制。

開啓保護

要開啓csrf攻擊保護,須要一下幾個步驟。

from flask_wtf.csrf import CSRFProtect

app.config['SECRET_KEY'] = 'you never guess'
CSRFProtect(app)
主要爲:導入方法,設置密鑰,進行保護。
這時候對於一個普通的form,若是你沒有
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />

flask會拋出http錯誤。

臨時關閉保護

那麼,如何臨時關閉csrf保護呢。
上面的代碼作修改:

去掉 CSRFProtect(app)
改成 csrf = CSRFProtect()

if __name__ == '__main__':中加入
csrf.init_app(app)

在不須要保護的路由上當加上:
@csrf.exempt

如此,臨時關閉了csrf。

http://docs.jinkan.org/docs/flask-wtf/csrf.html

相關文章
相關標籤/搜索