Flask_wtf除了可以做表單驗證,模板渲染之外,還可以防禦CSRF攻擊。要了解CSRF攻擊的原理,首先需要了解cookie和session的知識點。
cookie:在網站中,HTTP請求是無狀態的,也就是說,即使第一次和服務器連接並且登陸成功後,第二次請求服務器依然不能知道當前請求是哪個用戶。cookie的出現就是爲了解決這個問題。第一次登陸後服務器返回一些數據cookie給瀏覽器,然後瀏覽器保存在本地,當該用戶發送第二次請求的時候,就會自動把上次請求存儲的cookie數據自動的攜帶給服務器,服務器通過瀏覽器攜帶的數據就能判斷當前用戶是哪個了。cookie存儲的數據量有限,不同的瀏覽器有不同的存儲大小,一般不超過4kb,因此只能存少量數據。
1. cookie具有有效期,瀏覽器會自動清除到期的cookie。
2. cookie有域名的概念,只有訪問同一個域名,纔會把之前相同域名返回的cookie攜帶給服務器。
session:session和cookie的作用有點類似,都是爲了存儲用戶相關的數據。不同的是,cookie存儲在本地瀏覽器,而session存儲在服務器。存儲在服務器的數據會更加的安全,不容易被竊取。但是存儲在服務器上會佔用服務器資源。
cookie和session的使用方案:
在Web開發的過程中,cookie和session的使用已經出現了一些非常成熟的額方案,目前一般有兩種存儲方式:
1. 存儲在服務端:通過cookie存儲一個session_id,然後具體的數據則是保存在session中,如果用戶已經登陸,則服務器會在cookie中保存一個session_id,下次再次請求的時候,會把該session_id攜帶上來,服務器根據session_id在服務器中獲取用戶的session數據,就能知道該用戶是誰,以及之前保存的以下狀態信息。這種方案稱爲 server side session.
2. 將session數據加密,然後存儲在cookie中,這種方案稱爲client side session, flask採用的就是這種方案。但是也可以替換成其他的方案。
flask設置和刪除cookie:
1. 設置cookie
在flask中,需要通過返回的Response對象,設置cookie信息
from flask import Flask, request, Response
import config
app = Flask(__name__)
app.config.from_object(config)
@app.route('/')
def hello_world():
resp = Response("index page")
resp.set_cookie(key="username", value="tom")
return resp
if __name__ == '__main__':
app.run()
2. 刪除cookie
刪除cookie,使用Resopnse對象的delete_cookie(),指定cookie的key即可刪除
@app.route('/del/')
def del_cookie():
resp = Response("del cookie")
resp.delete_cookie("username")
return resp
3. 設置cookie的有效期
參數: max-age: 距離現在起多少秒後過期,單位是秒數,且max-age優先級高於expires參數,IE8以下不支持max-age
@app.route('/')
def hello_world():
resp = Response("index page")
resp.set_cookie(key="username", value="tom", max_age=30) # cookie距離現在30s過期
return resp
參數:expire:參數的格式爲datetime,設定過期的時間爲1天
@app.route('/')
def hello_world():
resp = Response("index page")
expires = datetime.datetime.now() + datetime.timedelta(days=1)
resp.set_cookie(key="username", value="tom", expires=expires) # cookie距離現在30s過期
return resp
如果沒有設置過期時間,那麼cookie將在瀏覽器關閉之後過期。
4. 設置cookie的有效域名
首先,需要設置域名,設置域名的步驟如下:
1. 修改電腦的host文件,以管理員身份運行cmd,然後cd到C盤system32/drivers目錄下
2. 輸入命令notepad hosts
3. 在host文件中,添加127.0.0.1 myff.com 以及127.0.0.1 cms.myff.com
4. 在flask中的config.py文件中,設置域名
SERVER_NAME = "myff.com:5000" # 設置域名與IP的映射
5. 在flask中註冊子域名的視圖函數cms.py,在視圖函數中設置子域名
# -*- coding: utf-8 -*-
from flask import Blueprint
bp_cms = Blueprint(name="cms", import_name=__name__, subdomain="cms")
@bp_cms.route("/")
def index():
return "cms 首頁"
此時,假設在首頁的視圖函數中,設置cookie的域名:
@app.route('/')
def hello_world():
resp = Response("index page")
expires = datetime.datetime.now() + datetime.timedelta(days=1)
# cookie距離現在30s過期
resp.set_cookie(key="username", value="tom", expires=expires, domain=".myff.com")
return resp
domain=".myff.com",如果域名前面不加點,則表示cookie只能在主域名下使用,不能在子域名下使用
在子域名cms 視圖函數中獲取cookie:
# -*- coding: utf-8 -*-
from flask import Blueprint, request
bp_cms = Blueprint(name="cms", import_name=__name__, subdomain="cms")
@bp_cms.route("/")
def index():
username = request.cookies.get("username")
return username or "cms 首頁"
session的基本概念:
session:session和cookie的作用有點類似,都是爲了存儲用戶相關的數據。不同的是,cookie存儲在本地瀏覽器,而session存儲在服務器。存儲在服務器的數據會更加的安全,不容易被竊取。但是存儲在服務器上會佔用服務器資源。與cookie不同的是,session是一個思路,一個概念,一個服務器存儲授權信息的解決方案。不同的服務器,不同的框架,不同的語言有不同的實現。雖然實現方案不一樣,但是他們的目的都是服務器爲了方便存儲數據的。session的出現,是爲了解決cookie存儲信息不安全的問題。
session還可以存儲到客戶端。客戶端發送驗證信息之後,服務器把相關的驗證信息進行加密,然後將加密後的數據存儲到cookie中,返回給瀏覽器,以後瀏覽器在請求服務器的時候,會自動將機密的session信息發送給服務端。服務端對數據進行解密之後,在進行驗證。flask中使用的就是這種機制。
在flask中,會自動將session機密,存儲在cookie中。所以需要在flask的配置文件中,設置以下加密用的字符串:
SECRET_KEY = os.urandom(24) # 設置flask中session加密的字符串 24長度的加密字符串
from flask import Flask, request, Response, session
import config
import datetime
from cms import bp_cms
app = Flask(__name__)
app.config.from_object(config)
@app.route('/')
def hello_world():
session["username"] = "tom"
return "Hello"
@app.route("/get_session/")
def get_session():
"""
獲取session
:return:
"""
username = session.get("username") # 推薦get方法獲取字典的鍵值
return username or "no session"
@app.route('/del_session/')
def del_session():
"""
刪除session
:return:
"""
session.pop("username") # 刪除session中某個字段
session.clear() # 刪除掉session中所有的內容
return "del success"
if __name__ == '__main__':
app.run()
在flask中,是將session中的字段,以及內容加密後,存儲在瀏覽器端的cookie,所以session 同樣可以設置過期的時間。
1. 設置session.permanent = True, 則session有效期爲31天
@app.route("/get_session/")
def get_session():
"""
獲取session
:return:
"""
username = session.get("username") # 推薦get方法獲取字典的鍵值
session.permanent = True # True 有效期31天
return username or "no session"
2. 在flask的配置文件config.py中,設置字段:
PERMANENT_SESSION_LIFETIME = timedelta(hours=12)
如果沒有設置session的有效期,那麼默認的session有效期爲31天