flask之session
1、 session简介
存储方式:通过cookie存储一个session_id,然后保存的具体内容在session中。如果用户已经登录,则会在cookie中记录一个session_id,再次进入的时候回从cookie中吧存储的session_id取出,并根据session_id从session中获取数据。
2、flask内置的session
使用加密的cookie保存,需要设置一个secret,与request一样基于上下文管理
本质是字典, 具有字典的操作方法
1 # 第一次请求进来 会把session所有的值都放入内存,对session的增删改查的操作都是在内存中进行的; 2 3 class SecureCookieSessionInterface(SessionInterface): 4 5 open_session --> 打开,获取 app.session_cookie_name获取加密的session(没有的话会创建) 6 然后进行解密 7 8 save_session --> 对操作完的sesison进行加密 保存
一些基本配置:
1 app.config['SESSION_COOKIE_NAME'] = '' 2 3 'SESSION_COOKIE_NAME': 'session', # 默认 4 'SESSION_COOKIE_DOMAIN': None, 5 'SESSION_COOKIE_PATH': None, 6 'SESSION_COOKIE_HTTPONLY': True, 7 'SESSION_COOKIE_SECURE': False, 8 'SESSION_REFRESH_EACH_REQUEST': True, 9 'PERMANENT_SESSION_LIFETIME': timedelta(days=31), # session的超时时间
大致流程:
刚进来创建 request_context 对象(request,初始化session(最开始为空))-->>
当接收到用户请求之后,会调用 Flask对象的 session_interface对象的open_session方法,以此来获取一个session对象。-->>
数据返回给用户,并且把内容中的session重新保存-->>
3 自定义session
根据内置session原理可以进行session的定制:
1 import uuid 2 import json 3 from flask.sessions import SessionInterface 4 from flask.sessions import SessionMixin 5 from itsdangerous import Signer, BadSignature, want_bytes 6 7 class MySession(dict, SessionMixin): 8 def __init__(self, initial=None, sid=None): 9 self.sid = sid 10 self.initial = initial 11 super(MySession, self).__init__(initial or ()) 12 13 def __setitem__(self, key, value): 14 super(MySession, self).__setitem__(key, value) 15 16 def __getitem__(self, item): 17 return super(MySession, self).__getitem__(item) 18 19 def __delitem__(self, key): 20 super(MySession, self).__delitem__(key)
1 class MySessionInterface(SessionInterface): 2 session_class = MySession 3 container = {} 4 5 def __init__(self): 6 import redis 7 self.redis = redis.Redis() 8 9 def _generate_sid(self): 10 return str(uuid.uuid4()) 11 12 def _get_signer(self, app): 13 if not app.secret_key: 14 return None 15 return Signer(app.secret_key, salt='flask-session', 16 key_derivation='hmac') 17 18 def open_session(self, app, request): 19 """ 20 程序刚启动时执行,需要返回一个session对象 21 """ 22 sid = request.cookies.get(app.session_cookie_name) 23 if not sid: 24 sid = self._generate_sid() 25 return self.session_class(sid=sid) 26 27 signer = self._get_signer(app) 28 try: 29 sid_as_bytes = signer.unsign(sid) 30 sid = sid_as_bytes.decode() 31 except BadSignature: 32 sid = self._generate_sid() 33 return self.session_class(sid=sid) 34 35 # session保存在redis中 36 # val = self.redis.get(sid) 37 # session保存在内存中 38 val = self.container.get(sid) 39 40 if val is not None: 41 try: 42 data = json.loads(val) 43 return self.session_class(data, sid=sid) 44 except: 45 return self.session_class(sid=sid) 46 return self.session_class(sid=sid) 47 48 def save_session(self, app, session, response): 49 """ 50 程序结束前执行,可以保存session中所有的值 51 如: 52 保存到resit 53 写入到用户cookie 54 """ 55 domain = self.get_cookie_domain(app) 56 path = self.get_cookie_path(app) 57 httponly = self.get_cookie_httponly(app) 58 secure = self.get_cookie_secure(app) 59 expires = self.get_expiration_time(app, session) 60 61 val = json.dumps(dict(session)) 62 63 # session保存在redis中 64 # self.redis.setex(name=session.sid, value=val, time=app.permanent_session_lifetime) 65 # session保存在内存中 66 self.container.setdefault(session.sid, val) 67 68 session_id = self._get_signer(app).sign(want_bytes(session.sid)) 69 70 response.set_cookie(app.session_cookie_name, session_id, 71 expires=expires, httponly=httponly, 72 domain=domain, path=path, secure=secure)
1 使用时,需要先新进行配置: 2 from flask import Flask 3 from flask import session 4 from pro_flask.utils.session import MySessionInterface 5 6 app = Flask(__name__) 7 8 app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT' 9 app.session_interface = MySessionInterface() 10 11 12 @app.route('/login.html', methods=['GET', "POST"]) 13 def login(): 14 print(session) 15 session['user1'] = 'alex' 16 session['user2'] = 'alex' 17 del session['user2'] 18 19 return "内容" 20 21 22 if __name__ == '__main__': 23 app.run()
3、flask_session
如果要实现保存到其他地方需要用到flask_session,可保存到(redis,memcached,filesystem,mongodb,sqlalchmey)
flask_session的使用:
redis存储方式:
import redis from flask import Flask, session from flask_session import Session app = Flask(__name__) app.debug = True app.secret_key = 'xxxx' app.config['SESSION_TYPE'] = 'redis' # session类型为redis app.config['SESSION_PERMANENT'] = False # 如果设置为True,则关闭浏览器session就失效。 app.config['SESSION_USE_SIGNER'] = False # 是否对发送到浏览器上session的cookie值进行加密 app.config['SESSION_KEY_PREFIX'] = 'session:' # 保存到session中的值的前缀 app.config['SESSION_REDIS'] = redis.Redis(host='127.0.0.1', port='6379', password='123123') # 用于连接redis的配置 Session(app) @app.route('/index') def index(): session['k1'] = 'v1' return 'xx' if __name__ == '__main__': app.run()
memcached
import redis from flask import Flask, session from flask_session import Session import memcache app = Flask(__name__) app.debug = True app.secret_key = 'xxxx' app.config['SESSION_TYPE'] = 'memcached' app.config['SESSION_PERMANENT'] = True # 如果设置为True,则关闭浏览器session就失效。 app.config['SESSION_USE_SIGNER'] = False # 是否对发送到浏览器上session的cookie值进行加密 app.config['SESSION_KEY_PREFIX'] = 'session:' # 保存到session中的值的前缀 app.config['SESSION_MEMCACHED'] = memcache.Client(['10.211.55.4:12000']) Session(app) @app.route('/index') def index(): session['k1'] = 'v1' return 'xx' if __name__ == '__main__': app.run()
filesystem
import redis from flask import Flask, session from flask_session import Session app = Flask(__name__) app.debug = True app.secret_key = 'xxxx' app.config['SESSION_TYPE'] = 'filesystem' app.config[ 'SESSION_FILE_DIR'] = '/Users/wupeiqi/PycharmProjects/grocery/96.Flask新课程/组件/2.flask-session' # session类型为redis app.config['SESSION_FILE_THRESHOLD'] = 500 # 存储session的个数如果大于这个值时,就要开始进行删除了 app.config['SESSION_FILE_MODE'] = 384 # 文件权限类型 app.config['SESSION_PERMANENT'] = True # 如果设置为True,则关闭浏览器session就失效。 app.config['SESSION_USE_SIGNER'] = False # 是否对发送到浏览器上session的cookie值进行加密 app.config['SESSION_KEY_PREFIX'] = 'session:' # 保存到session中的值的前缀 Session(app) @app.route('/index') def index(): session['k1'] = 'v1' session['k2'] = 'v1' return 'xx' if __name__ == '__main__': app.run()
mongodb
from flask import Flask, session from flask_session import Session import pymongo app = Flask(__name__) app.debug = True app.secret_key = 'xxxx' app.config['SESSION_TYPE'] = 'mongodb' app.config['SESSION_MONGODB'] = pymongo.MongoClient() app.config['SESSION_MONGODB_DB'] = 'mongo的db名称(数据库名称)' app.config['SESSION_MONGODB_COLLECT'] = 'mongo的collect名称(表名称)' app.config['SESSION_PERMANENT'] = True # 如果设置为True,则关闭浏览器session就失效。 app.config['SESSION_USE_SIGNER'] = False # 是否对发送到浏览器上session的cookie值进行加密 app.config['SESSION_KEY_PREFIX'] = 'session:' # 保存到session中的值的前缀 Session(app) @app.route('/index') def index(): session['k1'] = 'v1' session['k2'] = 'v1' return 'xx' if __name__ == '__main__': app.run()
sqlalchemy
import redis from flask import Flask, session from flask_session import Session as FSession from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) app.debug = True app.secret_key = 'xxxx' # 设置数据库链接 app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:123@127.0.0.1:3306/fssa?charset=utf8' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True # 实例化SQLAlchemy db = SQLAlchemy(app) app.config['SESSION_TYPE'] = 'sqlalchemy' # session类型为sqlalchemy app.config['SESSION_SQLALCHEMY'] = db # SQLAlchemy对象 app.config['SESSION_SQLALCHEMY_TABLE'] = 'session' # session要保存的表名称 app.config['SESSION_PERMANENT'] = True # 如果设置为True,则关闭浏览器session就失效。 app.config['SESSION_USE_SIGNER'] = False # 是否对发送到浏览器上session的cookie值进行加密 app.config['SESSION_KEY_PREFIX'] = 'session:' # 保存到session中的值的前缀 FSession(app) @app.route('/index') def index(): session['k1'] = 'v1' session['k2'] = 'v1' return 'xx' if __name__ == '__main__': app.run()
在写好代码后,不要着急运行,需要先执行进入终端执行一条创建数据库表的命令:
pro-flask xxxx$ python3 Type "help", "copyright", "credits" or "license" for more information. >>> from app import db >>> db.create_all()
应用程序比较小,用原生的加密ccokie 保存session(内置)
应用程序比较大,可以用redis(flask-session)
参考链接:https://www.cnblogs.com/big-handsome-guy/p/8550310.html