Flask-Session使用Redis

Flask-Session使用Redis

一、介绍

  • 在Flask中,session数据默认是以加密的cookie形式存储在用户的浏览器中的。
  • 但是,真正的session数据应该存储在服务器端。
  • Django框架会将session数据存储在数据库的djangosession表中,而Flask则可以通过第三方库如flask-session来实现,通常将session存储在Redis这样的内存数据库中。
  • 此外,Flask也可以使用JWT(JSON Web Tokens)来处理session。

二、使用

1. 安装

  • 要使用Flask的session功能,首先需要安装flask-session库:

    python 复制代码
    pip install flask-session

2.方式一

  • 创建Redis连接,并使用RedisSessionInterface来将session数据存储到Redis中。

  • 通过session字典来存储和获取数据。

  • 示例

    • python 复制代码
      from flask import Flask, session
      from flask_session.redis import RedisSessionInterface
      from redis import Redis
      
      app = Flask(__name__)  # 创建一个 Flask 应用对象
      app.debug = True  # 设置调试模式为开启
      app.config['SESSION_COOKIE_NAME'] = 'hello_session'  # 设置会话 cookie 名称,前端显示
      conn_redis = Redis(host="localhost", port=6379)  # 创建一个 Redis 连接对象,连接本地 Redis 服务器
      
      # 设置应用的会话接口为基于 Redis 的会话
      # app :Flask 应用对象
      # client :Redis 客户端对象
      # key_prefix :用于在数据库中存储会话的键名前缀
      app.session_interface = RedisSessionInterface(app, client=conn_redis, key_prefix='bruce')
      
      
      @app.route('/')
      def index():  # 定义路由处理函数
       session['serret'] = '123456'  # 设置会话变量 'serret'
       return 'index'  # 返回字符串 'index'
      
      
      if __name__ == '__main__':
       app.run()

3.方式二

  • 设置session的cookie名称和配置,指定session类型为redis。

  • 创建Redis连接对象,并使用Session类来初始化Flask应用。

  • 示例

    • python 复制代码
      from flask import Flask, session
      from flask_session import Session
      from redis import Redis
      
      app = Flask(__name__)
      app.session_cookie_name = 'hello_session'
      
      # 配置会话类型为redis,并指定redis的主机和端口
      app.config['SESSION_TYPE'] = 'redis'
      app.config['SESSION_REDIS'] = Redis(host='127.0.0.1', port=6379)
      
      # 将会话配置应用到Flask应用程序中
      Session(app)
      
      @app.route('/')
      def index():
       session['secret'] = '123456'
       return 'index'
      
      if __name__ == '__main__':
       app.run()

4.相关配置

python 复制代码
# 设置会话的cookie名称
app.session_cookie_name = 'hello_session'

# 配置会话类型为redis
app.config['SESSION_TYPE'] = 'redis'

# Redis配置
app.config['SESSION_REDIS'] = Redis(host='127.0.0.1', port=6379)
# Redis服务器的密码(如果有)
app.config['SESSION_REDIS_PASSWORD'] = 'password'  
# Redis数据库索引
app.config['SESSION_REDIS_DB'] = 0 

# 会话的过期时间,默认是31天
app.config['PERMANENT_SESSION_LIFETIME'] = 3600 * 24 * 31

# 是否对发送到浏览器端的cookie进行签名
app.config['SESSION_USE_SIGNER'] = True

# 是否需要HTTPS传输cookie
app.config['SESSION_COOKIE_SECURE'] = False

# 设置cookie的httponly属性,防止客户端脚本访问cookie
app.config['SESSION_COOKIE_HTTPONLY'] = True

# 设置cookie的SameSite属性,防止CSRF攻击
app.config['SESSION_COOKIE_SAMESITE'] = 'Lax'

三、源码解析

  • 使用Redis时,使用的是RedisSessionInterface

  • RedisSessionInterface继承ServerSideSessionInterface

  • open_session

    • python 复制代码
      def open_session(self, app, request):
       # 从cookie中获取会话ID
       sid = request.cookies.get(app.config["SESSION_COOKIE_NAME"])
      
       # 如果没有会话ID,生成一个新的,并返回
       if not sid:
           sid = self._generate_sid(self.sid_length)
           return self.session_class(sid=sid, permanent=self.permanent)
      
       # 如果会话ID已经签名,解除签名
       if self.use_signer:
           try:
               sid = self._unsign(app, sid)
           except BadSignature:
               sid = self._generate_sid(self.sid_length)
               return self.session_class(sid=sid, permanent=self.permanent)
      
       # 从数据库中检索会话数据
       store_id = self._get_store_id(sid)
       saved_session_data = self._retrieve_session_data(store_id)
      
       # 如果已保存会话存在,从文档中加载会话数据
       if saved_session_data is not None:
           return self.session_class(saved_session_data, sid=sid)
      
       # 如果已保存会话不存在,创建一个新会话
       sid = self._generate_sid(self.sid_length)
       return self.session_class(sid=sid, permanent=self.permanent)
  • save_session

    • python 复制代码
      def save_session(self, app, session, response):
       domain = self.get_cookie_domain(app)  # 获取cookie的域
       path = self.get_cookie_path(app)  # 获取cookie的路径
       name = self.get_cookie_name(app)  # 获取cookie的名称
      
       store_id = self._get_store_id(session.sid)  # 获取存储ID
      
       if session.accessed:  # 如果会话已访问
           response.vary.add("Cookie")  # 响应头中添加Vary信息
      
       if not session:  # 如果会话不存在
           if session.modified:  # 如果会话已修改
               self._delete_session(store_id)  # 删除会话
               response.delete_cookie(key=name, domain=domain, path=path)  # 从响应中删除cookie
               response.vary.add("Cookie")  # 响应头中添加Vary信息
           return  # 返回
      
       if not self.should_set_storage(app, session):  # 如果不应该设置存储
           return  # 返回
      
       self._upsert_session(app.permanent_session_lifetime, session, store_id)  # 更新或插入会话
      
       if not self.should_set_cookie(app, session):  # 如果不应该设置cookie
           return  # 返回
      
       # 获取额外的所需cookie设置
       value = self._sign(app, session.sid) if self.use_signer else session.sid  # 获取cookie的值
       expires = self.get_expiration_time(app, session)  # 获取cookie的过期时间
       httponly = self.get_cookie_httponly(app)  # 获取cookie的httponly设置
       secure = self.get_cookie_secure(app)  # 获取cookie的安全设置
       samesite = (
           self.get_cookie_samesite(app) if self.has_same_site_capability else None
       )  # 获取相同站点设置(如果支持)
      
       response.set_cookie(
           key=name,
           value=value,
           expires=expires,
           httponly=httponly,
           domain=domain,
           path=path,
           secure=secure,
           samesite=samesite,
       )  # 在响应中设置cookie
       response.vary.add("Cookie")  # 响应头中添加Vary信息
相关推荐
赵孝正2 分钟前
python对含数字的列名排序和去重
前端·javascript·python
SongYuLong的博客7 分钟前
python遍历目录下所有文件
前端·数据库·python
阿福不是狗8 分钟前
Python使用总结之应用程序有哪些配置方式?配置方式对比
linux·服务器·python
engchina9 分钟前
Python缓存利器:cachetools库详解
python·缓存·cachetools
重庆大傑12 分钟前
Redis 缓存问题及解决
数据库·redis·缓存
Mr.D学长1 小时前
竞赛选题 YOLOv7 目标检测网络解读
java·python
JH_vision1 小时前
如何更改 Python pip 源为国内源
python·pip
菜鸟赵大宝1 小时前
【Python】pycharm常用快捷键操作
python·pycharm
Roy Teng1 小时前
Python学习之小游戏--坦克大作战
python·学习·pygame
CV爱数码7 小时前
【脚本工具库】批量复制文件(附源码)
图像处理·python·深度学习·计算机视觉