0


【python】Flask之session使用

一、session机制

1.1 session的作用

由于http协议是一个无状态的协议,但网站基本上有登录使用的功能,这要求有状态管理,而session机制实现的就是这个功能

session基于cookie实现, 保存在服务端的键值对(形式:

{随机字符串:'xxxxxx'}

), 同时在浏览器中的cookie中也对应一相同的随机字符串,用来再次请求的时候验证

1.2 实现的原理

用户第一次请求后,将产生的状态信息保存在session中,可以把session当做一个容器,保存了正在使用的所有用户的状态信息,这段状态信息分配一个唯一的标识符用来标识用户的身份,将其保存在响应对象的cookie中
当第二次请求时,解析cookie中的标识符,拿到标识符后去session找到对应的用户的信息

二、使用案例

2.1 配置SECRET_KEY

flask的session是通过加密之后放到cookie中,有加密就有密钥用于解密,所以只要用到了flask的session模块就一定要配置"SECRET_KEY"这个全局宏
一般设置为24位的字符,配置方法一般有两种

2.1.1 配置方法一

  1. 新建一个config.py的文件配置secret_key

config.py

SECRET_KEY ='XXXXXXXXX'
  1. 在主运行文件里面添加config文件里面的内容

main.py

#encoding: utf-8from flask import Flask,session
import config
app = Flask(__name__)

2.1.2 配置方法二

直接在主运行文件里面配置。配置config的时候也是和操作字典是一样的
main.py

encoding: utf-8from flask import Flask,session
 
app = Flask(__name__)
app.config['SECRET_KEY']='XXXXX' 或者随机数(os.urandom(24))
# 或者
app.secret_key ='why would I tell you my secret key?'# key值可以使用随机数,或者自定义

2.2 操作session

2.2.1 设置session

from flask import Flask,session
import os
 
app = Flask(__name__)
app.config['SECRET_KEY']= os.urandom(24)# 设置[email protected]('/')defset():
     session['username']='liefyuan'# 设置“字典”键值对(正式开发时候,值需要session.get('user')获取)return'success'if __name__ =='__main__':
     app.run()

2.2.2 读取session

因为session就像字典一样所以,操作它的时候有两种方法:

  1. result = session['key'] :如果内容不存在,将会报异常
  2. result = session.get('key'):如果内容不存在,将返回None(推荐)
from flask import Flask,session
import os
 
app = Flask(__name__)
app.config['SECRET_KEY']= os.urandom(24)# 读取[email protected]('/get')defget():# session['username']# session.get('username')return session.get('username')if __name__ =='__main__':
     app.run()

2.2.3 删除session

#encoding: utf-8from flask import Flask,session
import os
app = Flask(__name__)
app.config['SECRET_KEY']= os.urandom(24)# 删除[email protected]('/delete/')defdelete():print session.get('username')
     session.pop('username',None) 或者 session['username']=Falseprint session.get('username')return'success'if __name__ =='__main__':
     app.run()

2.2.4 清除session中所有数据

#encoding: utf-8from flask import Flask,session
import os
 
app = Flask(__name__)
app.config['SECRET_KEY']= os.urandom(24)# 清除session中所有数据@app.route('/clear')defclear():print session.get('username')# 清除session中所有数据
     session.clear
     print session.get('username')return'success'if __name__ =='__main__':
     app.run()

三、session源码分析

依据上述session的原理,分析一下flask框架的session机制实现的过程

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

open_session和save_session

defopen_session(self, request):# 调用了app的session_interface对象的方法return self.session_interface.open_session(self, request)defsave_session(self, session, response):return self.session_interface.save_session(self, session, response)

app对象默认的

session_interface = SecureCookieSessionInterface()

SecureCookieSessionInterface

重写

SessionInterface

对象的

open_session

方法和

save_session

方法

classSecureCookieSessionInterface(SessionInterface):passdefopen_session(self, app, request):# 检测是否设置了secret_key参数,返回一个签名对象
        s = self.get_signing_serializer(app)if s isNone:returnNone# 去cookie中获取session信息
        val = request.cookies.get(app.session_cookie_name)# 如果是第一次请求,返回一个空的SecureCookieSession对象,会被交给请求上下文的session属性管理ifnot 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()defsave_session(self, app, session, response):# 获取cookie设置的域
        domain = self.get_cookie_domain(app)# 获取cookie设置的路径
        path = self.get_cookie_path(app)...# 检测SESSION_REFRESH_EACH_REQUEST参数配置ifnot 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)# 返回失效的时间点
        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)

请求上下文RequestContext的session属性是一个SecureCookieSession对象,可以将其看做一个字典

四、自定义session存储

通过分析flask的session实现机制,一般认为将session信息放在cookie中不够保险,那么可以实现session机制,思路是创建一个类继承SessionInterface,然后重写open_session方法和save_session方法,再替换app的session_interface属性即可

4.1 设置必要的配置参数

# 配置session存放的路径
MY_SESSION_PATH ='\session.json''SESSION_TYPE'='file'# 配置默认的seesion的配置参数
SECRET_KEY ='123'
SESSION_USE_SIGNER =True# session的有效期,单位:秒
PERMANENT_SESSION_LIFETIME =7200

4.2 创建SessionInterface的子类

from flask.sessions import*try:import cPickle as pickle
except ImportError:import pickle

import json
from uuid import uuid4
import time

# 我们需要自定义一个Session对象用来存储用户的信息,它使用一个唯一的id标识,模仿SecureCookieSession的实现方法classSecureFileSession(CallbackDict, SessionMixin):def__init__(self, initial=None, sid=None, permanent=None):defon_update(self):
            self.modified =True
        CallbackDict.__init__(self, initial, on_update)
        self.sid = sid  # session的标识if permanent:
            self.permanent = permanent  # 失效时间
        self.modified =False# 我们使用uuid作为签名,省略校验过程classNewSessionInterface(SessionInterface):def_generate_sid(self):returnstr(uuid4())classJsonFileSessionInterface(NewSessionInterface):# 用来序列化的包
    serializer = pickle
    session_class = SecureFileSession

    def__init__(self, app=None):
        self.app = app
        if app isnotNone:
            self.init_app(app)definit_app(self, app):"""
        替换app的session_interface属性
        :param app:
        :return:
        """
        app.session_interface = self._get_interface(app)def_get_interface(self, app):"""
        加载配置参数返回本身,必须配置'SESSION_TYPE'和'MY_SESSION_PATH'参数,否则使用默认的session
        :param app:
        :return:
        """
        config = app.config.copy()if config['SESSION_TYPE']=='file':ifnot config['MY_SESSION_PATH']:return SecureCookieSessionInterface()
            self.path = app.static_folder + config['MY_SESSION_PATH']# session文件路径
            self.permanent = total_seconds(app.permanent_session_lifetime)# 失效时间return self
        return SecureCookieSessionInterface()defopen_session(self, app, request):"""
        从文件中获取session数据
        :param app:
        :param request:
        :return:
        """# 获取session签名
        sid = request.cookies.get(app.session_cookie_name)
        permanent =int(time.time())+ self.permanent
        # 如果没有说明是第一次访问,返回空session对象ifnot sid:# 获取一个uuid
            sid = self._generate_sid()return self.session_class(sid=sid, permanent=permanent)withopen(self.path,'r', encoding='utf-8')as f:
            v = f.read()# 如果session为空,返回空session对象ifnot v:return self.session_class(sid=sid, permanent=permanent)try:
                val = json.loads(v)except ValueError as e:print('配置参数错误:{}'.format(e))return self.session_class(sid=sid, permanent=permanent)else:
                self.val = val
                # 通过sid获取信息
                data = val.get(sid)ifnot data:return self.session_class(sid=sid, permanent=permanent)# 判断以前的信息是否超时if permanent -int(data['permanent'])> self.permanent:return self.session_class(sid=sid, permanent=permanent)return self.session_class(data, sid=sid)defsave_session(self, app, session, response):"""
        保存session信息
        :param app:
        :param session:
        :param response:
        :return:
        """# 前面借鉴flask默认的实现方式
        domain = self.get_cookie_domain(app)
        path = self.get_cookie_path(app)ifnot session:if session.modified:
                response.delete_cookie(app.session_cookie_name,
                                       domain=domain, path=path)returnifnot self.should_set_cookie(app, session):return
        httponly = self.get_cookie_httponly(app)
        secure = self.get_cookie_secure(app)
        expires = self.get_expiration_time(app, session)# 将session信息保存在文件中
        session.update({'permanent':int(time.time())+ self.permanent})ifhasattr(self,'val')andisinstance(self.val,dict):
            self.val.update({session.sid:dict(session)})else:
            self.val ={session.sid:dict(session)}withopen(self.path,'w', encoding='utf-8')as f:
            result = json.dumps(self.val)
            f.write(result)
            response.set_cookie(app.session_cookie_name, session.sid,
                                expires=expires, httponly=httponly,
                                domain=domain, path=path, secure=secure)

4.3 初始化替换app的session_interface

app = Flask(__name__,template_folder='static/html')
app.config.update({'SECRET_KEY':'123','SESSION_USE_SIGNER':True,'SESSION_TYPE':'file','MY_SESSION_PATH':'\session.json'})from session_file import JsonFileSessionInterface
se = JsonFileSessionInterface(app=app)if __name__ =='__main__':
    app.run(host='127.0.0.1', port=80, debug=True)

经过上面的三步,可以将自己实现的session对象运用到flask项目中,采用的是文件存储session,实际项目中有redis、memcached、mysql等都可以存储session,将它们整合起来,于是flask_session插件就应运而生

五、flask_session扩展

flask_session插件就是官方推荐的session实现插件,整合了redis、memcached、mysql、file、mongodb等多种第三方存储session信息,实现原理就是上面自定义session所做的工作

5.1 安装

pip install Flask-Session

5.2 配置参数详解

flask_session初始化后,从app的配置中读取参数,比较重要的有:

设置session保存的位置,可以有多种配置,
SESSION_TYPE = ‘null’          : 采用flask默认的保存在cookie中;
SESSION_TYPE = ‘redis’         : 保存在redis中
SESSION_TYPE = ‘memcached’     : 保存在memcache
SESSION_TYPE ='filesystem': 保存在文件
SESSION_TYPE ='mongodb': 保存在MongoDB
SESSION_TYPE ='sqlalchemy': 保存在关系型数据库

SESSION_KEY_PREFIX ='session:':session存储时的键的前缀
SESSION_USE_SIGNER:是否为cookie设置签名来保护数据不被更改,默认是False;如果设置True,那么必须设置flask的secret_key参数;
SESSION_PERMANENT:是否使用永久会话,默认True,但是如果设置了PERMANENT_SESSION_LIFETIME,则这个失效;

SESSION_REDIS:
如果SESSION_TYPE = ‘redis’,那么设置该参数连接哪个redis,其是一个连接对象;如果不设置的话,默认连接127.0.0.1:6379/0for example:
SESSION_REDIS = redis.StrictRedis(host="127.0.0.1", port=6390, db=4)

5.3 常用的flask_session的配置

# 指明对session数据进行保护
SECRET_KEY ='123'
SESSION_USE_SIGNER =True# 指明保存到redis中
SESSION_TYPE ="redis"  
SESSION_REDIS = redis.StrictRedis(host="127.0.0.1", port=6390, db=4)# session的有效期,单位:秒
PERMANENT_SESSION_LIFETIME =7200

5.4 flask_session的使用流程

# extensions.py# 创建一个session对象from flask_session import Session
 # 创建一个Session的实例
session = Session()# 在app初始化时初始化session对象,即加载配置# __init__.pyfrom flask import Flask
app = Flask(__name__)
session.init_app(app=app)# task.pyfrom Flask import session

@app.route('/test', methods=['POST'])deftest():
    session.get('user',None)return""

5.5 设置session的过期时间栗子

  1. 引入包 from datetime import timedelta
  2. 配置有效期限 app.config[‘PERMANENT_SESSION_LIFETIME’] = timedelta(days=7) # 配置7天有效
  3. 设置 session.permanent = True
#encoding: utf-8from flask import Flask,session
from datetime import timedelta
import os 
app = Flask(__name__)
app.config['SECRET_KEY']= os.urandom(24)
app.config['PERMANENT_SESSION_LIFETIME']= timedelta(days=7)# 配置7天有效 # 设置[email protected]('/')defset():
    session['username']='liefyuan'
    session.permanent =Truereturn'success'
标签: python flask

本文转载自: https://blog.csdn.net/lluozh2015/article/details/123174344
版权归原作者 sysu_lluozh 所有, 如有侵权,请联系我们删除。

“【python】Flask之session使用”的评论:

还没有评论