18910140161

flask基础之session原理详解

顺晟科技

2021-06-16 10:44:39

162

Flask_session是Flask框架实现会话功能的插件,用来替代flask的会话实现机制。FLASK的默认会话信息保存在cookie中,不够安全灵活。

烧瓶的会话机制

会话用于什么?因为http协议是无状态协议,也就是说同一个用户的个请求和第二个请求没有关系,但是现在网站基本上都有登录的功能,需要有状态实现,而会话机制实现了这个功能。

实施原则:

在用户次请求后,生成的状态信息保存在会话中。此时,会话可以看作一个容器,保存所有用户在使用中的状态信息;这段状态信息被分配一个的标识符来标识用户的身份,并将其保存在响应对象的cookie中;第二次请求时,解析cookie中的标识符,获取标识符,然后转到session找到对应用户的信息。

简单使用

从烧瓶导入烧瓶,进程

app=Flask(__name__)

@app.route('/test1/')

def test():

session.setdefault('name ','肖明')

返回“确定”

if __name__=='__main__':

app.run(主机='127.0.0.1 ',端口=80,调试=真)

在flask中,如果我们想获取会话信息,可以直接通过flask的session获取,因为session是一个代理对象,代表当前请求上下文的session属性。

会话源代码分析

根据上述会话原理,本文分析了烧瓶框架会话机制的实现过程。

烧瓶对象使用打开会话方法和保存会话方法来打开和保存会话信息。创建请求上下文后,调用open_session方法获取用户信息,执行处理逻辑后,调用save_session方法保存用户信息。

打开_会话和保存_会话

def open_session(self,request):

#调用了应用的session_interface对象的方法

return self . session _ interface . open _ session(self,request)

def save_session(self,session,response):

return self . session _ interface . save _ session(self,session,response)

app对象默认为session _ interface=secureokiesessioninterface(),覆盖SessionInterface对象的open_session方法和save_session方法。

class secureokesessioniinterface(session interface):

及格

def open_session(self,app,request):

#检查secret_key参数是否已设置,并返回签名对象

s=self . get _ signing _ serializer(app)

如果s不是:

无返回

#转到cookie获取会话信息

val=request . cookies . get(app . session _ cookie _ name)

#如果是个请求,将返回一个空的安全工作会话对象,该对象将被移交给请求上下文的会话属性管理

如果不是val:

return self.session_class()

#获取会话的到期时间

max _ age=total _ seconds(app . permanent _ session _ lifetime)

try:

#解码会话信息以获取用户信息

数据=s.loads(val,max_age=max_age)

#返回包含用户信息的会话对象

return self.session_class(数据)

除了签名错误:

return self.session_class()

def save_session(self,app,session,response):

#获取cookie设置的域

domain=self . get _ cookie _ domain(app)

#获取cookie设置的路径

path=self.get_cookie_path(app)

.

#检查SESSION_REFRESH_EACH_REQUEST参数配置

如果不是self . shot _ set _ cookie(app,session):

返回

#返回SESSION_COOKIE_HTTPONLY参数配置

http nly=self . get _ cookie _ http nly(app)

#返回SESSION_COOKIE_SECURE参数配置

secure=self . get _ cookie _ secure(app)

#返回失败的时间点

expires=self . get _ expire _ time(app,session)

#加密用户数据

val=self . get _ signing _ serializer(app)。转储(dict(会话))

#设置cookie

response . set _ cookie(app . session _ cookie _ name,val,

expires=expires,httponly=httponly,

domain=domain,path=path,secure=secure)

RequestContext的会话属性requestcontext是一个SecureCookieSession对象,可以看作字典;

相关配置参数

SESSION_COOKIE_NAME:设置返回给客户端的COOKIE的名称,默认为“SESSION”;在头上回应;

SESSION_COOKIE_DOMAIN:设置会话的域,默认为当前服务器,因为SESSION是全局变量,可以应用于多个应用;

SESSION_COOKIE_PATH:设置会话的路径,即应该在哪些路由下设置COOKIE;如果不是,默认值为'/',将为所有路由设置cookies此参数和SESSION_COOKIE_DOMAIN是互斥的

SERVER_NAME:设置服务器的名称,一般不使用;

SESSION_cookie_SECURE:如果COOKIE标记为“安全”,浏览器将只使用基于HTTPS的请求发送COOKIE,并且应用程序必须使用HTTPS服务来启用此变量,默认情况下为False

APPLICATION_ROOT:设置应用程序的根路径;

session _ refresh _ each _ request :是否应该为每个请求设置cookie,默认值为True,如果为False,则必须显式调用set_cookie函数;

Session _ cookie _ httponly: cookie要和httponly标志一起设置,默认值为True,一般采用默认值。

PERMANENT _ SESSION _ LISTEVE:设置会话的有效期,即cookie的过期时间,单位为s,这个参数很重要,因为默认会话是的。

SESSION_COOKIE_HTTPONLY:默认值为true,表示允许js脚本访问COOKIE;

总结

默认情况下,flask通过SecureCookieSessionInterface对象管理会话,该对象覆盖SessionInterface对象的open_session方法和save_session方法,并加密用户数据并将其存储在cookie中。

自定义会话存储

通过分析flask的会话实现机制,一般认为把会话信息放在cookie中是不安全的,可以实现自己的会话机制。想法是创建一个类来继承SessionInterface,然后重写open_session方法和save_session方法,然后用我们的类替换app的session_interface属性。

例如,我想将会话信息保存在一个会话中

步骤1:设置必要的配置参数

#配置存储会话的路径

MY_SESSION_PATH='\session.json '

SESSION_TYPE'='文件'

#配置默认的seesion配置参数

SECRET_KEY='123 '

会话_使用_签名=真

#会话的有效期,以秒为单位

_会话_生命周期=7200

步骤2:创建自己的会话接口子类

来自flask.sessions导入*

try:

进口泡菜

除了导入错误:

进口泡菜

导入json

从uuid导入uuid4

导入时间

#我们需要定制一个Session对象来存储用户信息,它使用一个的id来模仿SecureCookieSession的实现方法

class securefilession(callback dict,SessionMixin):

def __init__(自身,初始=无,sid=无,=无):

def on_update(self):

自我修改=真

CallbackDict。__init__(自我,初始,on_update)

Self.sid=sid #会话

if permanent:

Self.permanent=#到期时间

自修改=假

#我们使用uuid作为签名,省略了验证过程

class newsessioniinterface(sessioniinterface):

def _generate_sid(self):

返回字符串(uuid4())

类JsonFileSessionInterface(NewSessionInterface):

#用于序列化的包

串行器=泡菜

session _ class=SecureFileSession

def __init__(self,app=None):

self.app=app

如果应用程序不是None:

self.init_app(app)

def init_app(self,app):

'''

替换应用的session_interface属性

:param app:

:return:

'''

app.session_interface=self。_get_interface(应用程序)

def _get_interface(self,app):

'''

加载配置参数返回自身,必须配置“会话类型”和“我的会话路径”参数,否则将使用默认会话

:param app:

:return:

'''

config=app.config.copy()

if config[' SESSION _ TYPE ']=' file ' :

如果没有配置['MY_SESSION_PATH']:

返回SecureCookieSessionInterface()

自我。PATH=app。静态文件夹配置[' MY _ SESSION _ PATH ']# SESSION文件路径

自我。permanent=total _ sec(应用。_会话_生存期)#失效时间

回归自我

返回SecureCookieSessionInterface()

def open_session(self,app,request):

'''

从文件中获取会议数据

:param app:

:param request:

:return:

'''

# 获取会议签名

sid=请求。饼干。get(app。session _ cookie _ name)

permanent=int(时间。time())self。的

# 如果没有说明是次访问,返回空会议对象

如果不是sid:

# 获取一个全局识别

sid=self ._generate_sid()

回归自我。session _ class(sid=sid,=)

使用open(self.path,' r ',编码='utf-8 ')作为f:

v=f.read()

# 如果会议为空,返回空会议对象

如果不是v:

回归自我。session _ class(sid=sid,=)

try:

val=json.loads(v)

除了作为e:的值错误

"打印("配置参数错误:{}'.格式(e))

回归自我。session _ class(sid=sid,=)

else:

self.val=val

# 通过(同suddenionosphericdisturbance)电离层的突然骚扰获取信息

data=val.get(sid)

如果不是数据:

回归自我。session _ class(sid=sid,=)

# 判断以前的信息是否超时

if permanent-int(data[' permanent '])self。:

回归自我。session _ class(sid=sid,=)

return self.session_class(data,sid=sid)

def save_session(self,app,session,response):

'''

保存会议信息

:param app:

:param session:

:参数响应:

:return:

'''

# 前面借鉴瓶默认的实现方式

domain=self。get _ cookie _ domain(app)

path=self.get_cookie_path(app)

如果不是会话:

if session.modified:

回应。delete _ cookie(应用程序。session _ cookie _ name,

domain=domain,path=path)

返回

如果不是自我。shot _ set _ cookie(应用程序,会话):

返回

http nly=self。get _ cookie _ http nly(app)

安全=自我。get _ cookie _ secure(app)

expires=selfget _ expire _ time(应用程序,会话)

# 将会议信息保存在文件中

会话。update({ ' permanent ' : int(time。time())self。})

if hasattr(self,‘val’)和isinstance(self.val,dict):

自我。瓦尔。更新({ session。sid 3: dict(session)})

else:

自我。val={ session。sid : dict(会话)

带有open(self.path,' w ',编码='utf-8 ')作为f:

result=json.dumps(self.val)

f.write(结果)

回应。set _ cookie(应用程序。session _ cookie _ name,session.sid,

expires=expires,httponly=httponly,

domain=domain,path=path,secure=secure)

第三步:初始化替换应用的会话接口

app=Flask(__name__,template_folder='static/html ')

app.config.update({

SECRET_KEY':'123 ',

SESSION _ USE _ SIGNER ' :True路径路径,

会话类型' : '文件,

MY _ SESSION _ PATH ' : ' \ SESSION。JSON ' })

从会话文件导入JsonFileSessionInterface

se=jsonfilessioninterface(app=app)

if __name__=='__main__':

app.run(主机='127.0.0.1 ',端口=80,调试=真)

小结

经过上面的三步,我们就可以将自己实现的会议对象运用到瓶项目中,我们采用的是文件存储会话,实际项目中有redis,memcached,mysql等都可以存储会话,将它们整合起来,于是烧瓶_会话插件就应运而生了。

烧瓶_会话扩展

烧瓶_会话插件就是官方推荐的会议实现插件,整合了redis,memcached,mysql,file,mongodb等多种第三方存储会议信息,它的实现原理就是我上面自定义会议所做的工作。

安装

管道安装烧瓶-会话

配置参数详解

烧瓶_会话初始化后,会从应用的配置中读取参数,比较重要的有:

沙吾提会话数云娥,吴亚玲苏亚娜苏亚娜苏亚娜苏亚娜苏亚娜苏亚娜苏亚娜苏亚娜苏亚娜苏亚娜苏亚娜苏亚娜苏亚娜苏亚娜苏亚娜苏亚娜苏亚娜,

SESSION_TYPE='null' :阿九弗拉斯克黄公子饼干!饼干何曰;

SESSION_TYPE='redis' :云娥再说一遍何曰

session _ type=' memcached ' :云娥快取记忆体

session _ type=' filesystem ' :孙悟空(音译)

session _ type=' mongodb ' :云娥蒙戈布

session _ type=' sqlalchemy ' :陆恭蕙

session _ key _ prefix=' session 3360 ' 3330 session你是谁

SESSION_USE_SIGNER:切望阿望阿望阿望阿望阿望阿望阿望阿望阿望阿望阿望阿望阿望阿望阿望阿望阿望阿望阿望饼干!饼干胡志明,胡志明,胡志明,胡志明,胡志明,胡志明,胡志明,胡志明,胡志明,胡志明,胡志明,胡志明,胡志明,胡志明,胡志明,胡志明,胡志明,胡志明,胡志明,胡志明,胡志明,胡志明,黄公子假的;唉哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟是真的,我的天啊弗拉斯克什么事secret _ key-密码哎哎哎;

会话:切望着切望着切望着切望着,黄头发是真的,魏冄_会话_生命周期,哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟;

SESSION_REDIS:

唉呀SESSION_TYPE='redis ',朱庇特胡安特胡安特胡安特瑞迪斯,云娥与云娥;喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂喂,黄公子127.0.0.1:6379/0

例如:

SESSION_REDIS=redis .strictredis(主机='127.0.0.1 ',端口=6390,db=4)

范仲淹!范仲淹!范仲淹!范仲淹页:1。

何钟泰呢烧瓶_会话-烧瓶\u阶段作业绿筠小姐

#年#月#日阿云娥会话数

SECRET_KEY='123 '

会话_使用_签名=真

#年#月#日诶哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟再说一遍何曰

会话类型='redis '

SESSION_REDIS=redis .strictredis(主机='127.0.0.1 ',端口=6390,db=4)

#会话阶段作业伊留申伊留申伊留申伊留申伊留申伊留申伊留申伊留申伊留申伊留申伊留申伊留申伊留申伊留申伊留申伊留申,哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟:哈哈哈

permanent _ session _ lifetime=7200

烧瓶_会话-烧瓶\u阶段作业张居正(音译)

# extensions.py

#年哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼会话数绿筠

从烧瓶_会话汇入阶段作业

#年哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼哼会话数云娥

会话=会话()

#年#月#日哦,天啊app(应用程序)哎哎哎哎哎哎会话数绿筠,唉哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟

_ init _ .皮。巴拉圭

从瓶进口瓶

app=Flask(__name_)

session.init_app(app=app)

# task.py

从瓶汇入阶段作业

@app.route('/test ',methods=['POST '))

极好的测试()

session.get('user ',None)

返回""

相关文章
我们已经准备好了,你呢?
2024我们与您携手共赢,为您的企业形象保驾护航