Flask的session——关于写扩展所学习到的
这两天端午节。趁着端午节没事干,写了个flask的扩展——flask-RedisSession
在flask中使用该扩展可以让你借助redis数据库轻松获得server-side session.
这个flask扩展可以使用pip install flask-redissession
获得,也可以进入flask-redissession给我个star 给我提问题/建议...
由于写这个扩展包的需要,我重新研究了一下flask中session的部分。以下部分是我扩展包中的过程。
open_session
当用户发送请求的时候,request被传到服务器。由于使用的是server-side session,这个request中就包含一个sessionID。后台程序调用open_session
方法,来解析这个request,获得session。具体的过程如下:
-
后台程序解析request,通过
session_cookie_name
获得sessionID
(如果没有,就设置为None
) -
检验这个
sessionID
是否存在。如果不存在,则生成一个sessionID,然后创建一个session,并返回给客户端 -
sessionID
存在。检验是否使用SECRET_KEY
来签名。如果使用,则调用Signer
函数生成Signer对象,并对这个sessionID进行unsigner
操作。signer = Signer(app.secret_key, salt='flask-redis-session', key_derivation='hmac') sessionid = signer.unsign(sessionid).decode('utf-8')
-
根据unsigner操作获得的结果在redis数据库中查找对应的session(已序列化),并对session反序列化。如果根据sessionID没找到,则创建一个新的session并返回给客户端
-
把查找到的session返回给客户端
save_session
如果session发生改变,就会调用这个方法(先删除原session,再set_session
)。
在save_session中,我们需要知道:
-
把session被序列化后的东西存入redis数据库:
以下是序列化的代码serialize_session = self.serialization_method.dumps(dict(session))
-
需要在每次session发生改变的时候重置过期时间。
-
如果使用
SECRET_KEY
进行签名,则在给用户返回sessionID之前,需要对原sessionID进行签名:session_id = Signer(app.secret_key, salt='flask-redis-session', key_derivation='hmac').sign(session.session_id.encode('utf-8')) #对session_id进行解码,转为str session_id = session_id.decode('utf-8')
-
调用
set_session
为用户设置新的session。其中传输的值为签名后的sessionID
总结
- redis数据库使用字符串对象存储session。
键:未签名的sessionID
值:序列化的session - 用户请求中(request)的sessionID是已签名sessionID,在服务器中需要unsign操作才能获得真正的sessionID
- 当session发生改变的时候,服务器需要在redis中删除原session,并调用
delete_cookie
让客户端删除这个session;然后向redis中写入新的session(需要序列化),并通过调用set_session
把签名后的sessionID回传给客户端