Flask 的 Session
1. Flask 的 session 原理
- 当请求刚进来时,Flask 会读取cookie中session对应的值:eyjrmindxxx,将该值解密并反序列化成一个字典,并且放入内存中以便视图函数使用
- 当请求结束时,flask会读取内存中字典的值,进行序列化+加密,最后写入用户cookie中

2. Flask 的 session 介绍
- Flask 中的 session 本质上继承了 python 中的字典,字典有的方法它都能使用,且在返回给浏览器的时候会将这个字典变成密文写入cookie中
3. session 的全局配置项
{
'PERMANENT_SESSION_LIFETIME': timedelta(days=31), # session 的有效时间
'SESSION_COOKIE_NAME': 'session', # session 在 cookie 中的名字
'SESSION_COOKIE_SAMESITE': None,
'SESSION_COOKIE_DOMAIN': None,
'SESSION_COOKIE_PATH': None,
'SESSION_COOKIE_HTTPONLY': True,
'SESSION_COOKIE_SECURE': False,
'SESSION_REFRESH_EACH_REQUEST': True, # 是否当用户访问了该页面重新计算session时间
}
4. session 的使用
# app.py
from flask import Flask, request, session
app = Flask(__name__)
app.secret_key = 'session_salt' # 设置session的“盐”,一定要设置否则无法使用 session
@app.route('/index', methods=['GET', 'POST'])
def index():
session['name'] = 'Kevin' # 设置 session
session_name_data = session.get('name') # 获取 session
print(session_name_data) # Kevin
del session['name'] # 删除 session
return 'index'
if __name__ == '__main__':
app.run()
Flask 的 Session 源码分析
- flask 默认通过 SecureCookieSessionInterface 对象管理 Session
- SecureCookieSessionInterface 对象下最重要的两个方法就是 open_session方法 和 save_session方法
- open_session方法 和 save_session方法的说明
- open_session方法: 获取session,从cookie中获取session的信息,然后session信息进行解密+反序列化得到相关的session内容
- save_session方法: 保存session,将需要保存的内容加密+序列化,然后写入cookie中
class SecureCookieSessionInterface(SessionInterface):
……
# 获取 session 的方法
def open_session(self, app, request):
# 检测是否设置了secret_key参数,返回一个签名对象
s = self.get_signing_serializer(app)
if s is None:
return None
# 去cookie中获取session信息
val = request.cookies.get(app.session_cookie_name)
# 如果是第一次请求,返回一个空的SecureCookieSession对象,会被交给请求上下文的session属性管理
if not val:
return self.session_class()
# 获取session的失效时间
max_age = total_seconds(app.permanent_session_lifetime)
try:
# 对session信息进行解码+反序列化得到用户信息
data = s.loads(val, max_age=max_age)
# 返回有用户信息的session对象
return self.session_class(data)
except BadSignature:
return self.session_class()
# 保存 session 的方法
def save_session(self, app, session, response):
# 获取cookie设置的域
domain = self.get_cookie_domain(app)
# 获取cookie设置的路径
path = self.get_cookie_path(app)
if not session:
if session.modified:
response.delete_cookie(
app.session_cookie_name, domain=domain, path=path
)
return
if session.accessed:
response.vary.add("Cookie")
# 检测SESSION_REFRESH_EACH_REQUEST参数配置
if not self.should_set_cookie(app, session):
return
# 返回SESSION_COOKIE_HTTPONLY参数配置
httponly = self.get_cookie_httponly(app)
# 返回SESSION_COOKIE_SECURE参数配置
secure = self.get_cookie_secure(app)
# 返回SESSION_COOKIE_SAMESITE参数配置
samesite = self.get_cookie_samesite(app)
# 返回失效的时间点
expires = self.get_expiration_time(app, session)
# 将用户的数据加密+序列化
val = self.get_signing_serializer(app).dumps(dict(session))
# 设置cookie
response.set_cookie(
app.session_cookie_name,
val,
expires=expires,
httponly=httponly,
domain=domain,
path=path,
secure=secure,
samesite=samesite,
)
- app.session_interface 说明:
- app.session_interface 是指定 Flask 使用什么对象对session进行管理
- 当 app.session_interface 被修改了,那么就会使用你所指定的对象进行对session的管理
- flask-session 模块也是通过修改 app.session_interface 的值来确定session保存在那个位置
from flask import Flask
from flask.sessions import SecureCookieSessionInterface
app = Flask(__name__)
app.session_interface = SecureCookieSessionInterface()
flask-session模块
1. PIL的安装
pip3 install flask-session -i https://pypi.douban.com/simple # 使用豆瓣的镜像
2. 介绍
- flask-session 是 flask 框架的 session组件,由于原来 flask 内置 session 使用签名 cookie 保存,该组件则将支持 session 保存到多个地方,如:
- null: 采用flask默认的保存在cookie中
- redis: 将数据保存到 redis 缓存中
- memcached: 将数据保存到 memcached 缓存中
- filesystem: 将数据保存到文件中
- mongodb: 将数据保存到 mongodb 数据库中
- sqlalchmey:将数据存到关系型数据库
- flask-session 实际是通过修改 app.session_interface 的值来确定 session 保存在那个位置
- 在 Flask 的 Session 源码分析栏目中有提到 app.session_interface 的说明

3. 使用场景
- 如果应用程序比较小,就用原生的加密ccokie 保存session(即: Flask 内置session)
- 如果应用程序比较大,就用flask-session(即: redis)
4. 所有配置项
# 可以在 flask-session 所提供的 Session 类源码中查看所有的配置信息
# from flask.ext.session import Session # 旧版本的写法
from flask_session import Session # 新版本的写法
Session
# ------------------ 公共配置 --------------------------
app.config['SESSION_TYPE'] = 'null' # session所保存的位置
app.config['SESSION_PERMANENT'] = True # 是否使用永久会话,默认True,但是如果设置了PERMANENT_SESSION_LIFETIME,则这个失效
app.config['SESSION_USE_SIGNER'] = False # 是否为cookie设置签名来保护数据不被更改,默认是False;如果设置True,那么必须设置flask的secret_key参数
app.config['SESSION_KEY_PREFIX'] = 'session:' # session存储时的key的前缀
# ------------------ redis的相关配置 --------------------------
app.config['SESSION_REDIS'] = None # 配置redis连接对象(即: 设置该连接那个redis),如果不设置默认使用本地ip+6379端口的redis进行连接
# ------------------ memcached的相关配置 --------------------------
app.config['SESSION_MEMCACHED'] = None # 配置memcached连接对象(即: 设置该连接那个memcached),如果不设置默认就会报错
# ------------------ filesystem的相关配置 --------------------------
app.config['SESSION_FILE_DIR'] = os.path.join(os.getcwd(), 'flask_session') # 文件路径
app.config['SESSION_FILE_THRESHOLD'] = 500 # 存储session的个数如果大于这个值时,就要开始进行删除了
app.config['SESSION_FILE_MODE'] = 384 # 文件权限类型,默认值: 0o600
# ------------------ mongodb的相关配置 --------------------------
app.config['SESSION_MONGODB'] = None # 所要连接的MongoDB数据库
app.config['SESSION_MONGODB_DB'] = 'flask_session' # MongoDB 数据库名称
app.config['SESSION_MONGODB_COLLECT'] = 'sessions' # MongoDB 表名称
# ------------------ sqlalchmey的相关配置 --------------------------
app.config['SESSION_SQLALCHEMY'] = None # SQLAlchemy对象
app.config['SESSION_SQLALCHEMY_TABLE'] = 'sessions' # 表名称(即: session 数据保存在该表下)
5. 使用
- redis
# app.py
import redis
from flask import Flask, render_template, session
# from flask.ext.session import Session # 旧版本的写法
from flask_session import Session # 新版本的写法
app = Flask(__name__)
app.secret_key = 'session_salt' # 设置session的“盐”
# ----------------- flask-session的相关配置-start -------------------------
app.config['SESSION_TYPE'] = 'redis' # session所保存的位置
app.config['SESSION_REDIS'] = redis.Redis(host='127.0.0.1', port=6379, password='') # 配置redis连接对象(即: 设置该连接那个redis),如果不设置默认使用本地ip+6379端口的redis进行连接
app.config['SESSION_PERMANENT'] = True # 是否使用永久会话,默认True,但是如果设置了PERMANENT_SESSION_LIFETIME,则这个失效
app.config['SESSION_USE_SIGNER'] = False # 是否为cookie设置签名来保护数据不被更改,默认是False;如果设置True,那么必须设置flask的secret_key参数
app.config['SESSION_KEY_PREFIX'] = 'session:' # session存储时的key的前缀
Session(app)
# ----------------- flask-session的相关配置-end -------------------------
@app.route('/login')
def login():
session['user'] = 'Kevin' # 设置 session
return render_template('login.html')
@app.route('/index')
def index():
print(session.get('user')) # 获取 session
return render_template('index.html')
if __name__ == '__main__':
app.run()
- memcached
# app.py
import memcache
from flask import Flask, render_template, session
# from flask.ext.session import Session # 旧版本的写法
from flask_session import Session # 新版本的写法
app = Flask(__name__)
app.secret_key = 'session_salt' # 设置session的“盐”
# ----------------- flask-session的相关配置-start -------------------------
app.config['SESSION_TYPE'] = 'memcached' # session所保存的位置
app.config['SESSION_MEMCACHED'] = memcache.Client(['10.211.55.4:12000']) # 配置memcached连接对象(即: 设置该连接那个memcached),如果不设置默认就会报错
app.config['SESSION_PERMANENT'] = True # 是否使用永久会话,默认True,但是如果设置了PERMANENT_SESSION_LIFETIME,则这个失效
app.config['SESSION_USE_SIGNER'] = False # 是否为cookie设置签名来保护数据不被更改,默认是False;如果设置True,那么必须设置flask的secret_key参数
app.config['SESSION_KEY_PREFIX'] = 'session:' # session存储时的key的前缀
Session(app)
# ----------------- flask-session的相关配置-end -------------------------
@app.route('/login')
def login():
session['user'] = 'Kevin' # 设置 session
return render_template('login.html')
@app.route('/index')
def index():
print(session.get('user')) # 获取 session
return render_template('index.html')
if __name__ == '__main__':
app.run()
- filesystem
# app.py
from flask import Flask, render_template, session
# from flask.ext.session import Session # 旧版本的写法
from flask_session import Session # 新版本的写法
app = Flask(__name__)
app.secret_key = 'session_salt' # 设置session的“盐”
# ----------------- flask-session的相关配置-start -------------------------
app.config['SESSION_TYPE'] = 'filesystem' # session所保存的位置
app.config['SESSION_FILE_DIR'] = '/Users/wupeiqi/PycharmProjects/grocery/96.Flask新课程/组件/2.flask-session' # 文件路径
app.config['SESSION_FILE_THRESHOLD'] = 500 # 存储session的个数如果大于这个值时,就要开始进行删除了
app.config['SESSION_FILE_MODE'] = 384 # 文件权限类型,默认值: 0o600
app.config['SESSION_PERMANENT'] = True # 是否使用永久会话,默认True,但是如果设置了PERMANENT_SESSION_LIFETIME,则这个失效
app.config['SESSION_USE_SIGNER'] = False # 是否为cookie设置签名来保护数据不被更改,默认是False;如果设置True,那么必须设置flask的secret_key参数
app.config['SESSION_KEY_PREFIX'] = 'session:' # session存储时的key的前缀
Session(app)
# ----------------- flask-session的相关配置-end -------------------------
@app.route('/login')
def login():
session['user'] = 'Kevin' # 设置 session
return render_template('login.html')
@app.route('/index')
def index():
print(session.get('user')) # 获取 session
return render_template('index.html')
if __name__ == '__main__':
app.run()
- mongodb
# app.py
import pymongo
from flask import Flask, render_template, session
# from flask.ext.session import Session # 旧版本的写法
from flask_session import Session # 新版本的写法
app = Flask(__name__)
app.secret_key = 'session_salt' # 设置session的“盐”
# ----------------- flask-session的相关配置-start -------------------------
app.config['SESSION_TYPE'] = 'mongodb' # session所保存的位置
app.config['SESSION_MONGODB'] = pymongo.MongoClient('mongodb://localhost:27017/') # 所要连接的MongoDB数据库
app.config['SESSION_MONGODB_DB'] = 'mongo的db名称(数据库名称)' # MongoDB 数据库名称
app.config['SESSION_MONGODB_COLLECT'] = 'mongo的collect名称(表名称)' # MongoDB 表名称
app.config['SESSION_PERMANENT'] = True # 是否使用永久会话,默认True,但是如果设置了PERMANENT_SESSION_LIFETIME,则这个失效
app.config['SESSION_USE_SIGNER'] = False # 是否为cookie设置签名来保护数据不被更改,默认是False;如果设置True,那么必须设置flask的secret_key参数
app.config['SESSION_KEY_PREFIX'] = 'session:' # session存储时的key的前缀
Session(app)
# ----------------- flask-session的相关配置-end -------------------------
@app.route('/login')
def login():
session['user'] = 'Kevin' # 设置 session
return render_template('login.html')
@app.route('/index')
def index():
print(session.get('user')) # 获取 session
return render_template('index.html')
if __name__ == '__main__':
app.run()
- sqlalchmey
pip3 install flask-sqlalchemy -i https://pypi.douban.com/simple # 使用豆瓣的镜像
# app.py
from flask import Flask, render_template, session
# from flask.ext.session import Session # 旧版本的写法
from flask_session import Session # 新版本的写法
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.secret_key = 'session_salt' # 设置session的“盐”
# ----------------- flask-session的相关配置-start -------------------------
# 设置数据库链接
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://数据库用户名:密码,如果没有密码可以空着不填@ip地址:端口号/数据库名称?charset=utf8'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
# 实例化SQLAlchemy
db = SQLAlchemy(app)
app.config['SESSION_TYPE'] = 'sqlalchemy' # session所保存的位置
app.config['SESSION_SQLALCHEMY'] = db # SQLAlchemy对象
app.config['SESSION_SQLALCHEMY_TABLE'] = 'session' # 表名称(即: session 数据保存在该表下)
app.config['SESSION_PERMANENT'] = True # 是否使用永久会话,默认True,但是如果设置了PERMANENT_SESSION_LIFETIME,则这个失效
app.config['SESSION_USE_SIGNER'] = False # 是否为cookie设置签名来保护数据不被更改,默认是False;如果设置True,那么必须设置flask的secret_key参数
app.config['SESSION_KEY_PREFIX'] = 'session:' # session存储时的key的前缀
Session(app)
# ----------------- flask-session的相关配置-end -------------------------
@app.route('/login')
def login():
session['user'] = 'Kevin' # 设置 session
return render_template('login.html')
@app.route('/index')
def index():
print(session.get('user')) # 获取 session
return render_template('index.html')
if __name__ == '__main__':
app.run()
# 在终端上执行创建数据库表
>>> from app import db
>>> db.create_all() # 创建数据库表
← HTML模板 WTForms 组件 →