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天
var code = "2fae2304-208f-474c-abd5-a8bbcf43dec9"