通过flask-session使flask和flask-socketio共用服务端会话(Server-side sessions)

由于通讯机制的不同,导致flask-socketio与flask无法共用服务端会话,flask-socketio初始化时有个参数manage_session,默认是True,意思是由flask-socketio独立管理自己的会话,如果设置为False,则指明会话交由flask管理,但这仅限于共享,即在socketio建议连接之前由flask生成的会话,可以被socketio获取到,也可以在socketio内进行修改,但问题在于由socketio修改后的会话,却不能被flask监测并使用,即flask那边仍是原来的值,官方解释如下

💡我自己琢磨着,虽然可以共享了,但是会话数据仍然是各自存储,就像命名空间一样,各自互不影响,你能看到,只是使用了副本,并不是地址引用。

解决以上问题的核心关键,就是把会话数据存储在一个公用的地方,如文件,数据库等,大家都可以自由读写,这样就实现了会话共享。

一,安装flask-session

$ pip install Flask-Session
# 推荐使用redis存储,所以Redis扩展需要同步安装,或独立安装,以下命令可以同步安装
$ pip install "Flask-Session[redis]"
# 或单独安装
$ pip install Redis

# 其他可用存储类型请参阅 https://flask-session.readthedocs.io/en/latest/installation.html#available-storage-options

二,初始化配置

# 方式一,未使用蓝图项目,直接初始化
# project_dir/app.py,项目入口文件
from flask import Flask, session
from flask_session import Session
from flask_socketio import SocketIO
from redis import Redis

app = Flask(__name__)

# 设置session
app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_REDIS'] = Redis(host='localhost', port=6379, db=15)
app.config['SESSION_KEY_PREFIX'] = 'Flaskr'
Session(app)

socketio = SocketIO(app, cors_allowed_origins='*', manage_session=False)  # , async_mode='eventlet'

@app.route('/set/')
def set():
    session['key'] = 'value'
    return 'ok'

@app.route('/get/')
def get():
    return session.get('key', 'not set')

if __name__ == '__main__':
    socketio.run(app, '0.0.0.0', debug=True)
# 方式二,使用蓝图项目,创建应用后再初始化
# project_dir/flaskr/__init__.py  项目工厂初始化文件
from flask import Flask
from flask_session import Session
from flask_socketio import SocketIO
from redis import Redis

# 全局实例化对象
socketio = SocketIO()
sess = Session()

def creat_app():
    app = Flask(__name__, instance_relative_config=True, static_url_path='/flaskr/static')
    # 设置session
    app.config['SESSION_TYPE'] = 'redis'
    app.config['SESSION_REDIS'] = Redis(host='localhost', port=6379, db=15)
    app.config['SESSION_KEY_PREFIX'] = 'Flaskr'

    # ...其他代码

    # session初始化当前App
    sess.init_app(app)
    # socketIO初始化当前App
    socketio.init_app(app, cors_allowed_origins='*', manage_session=False)  # , async_mode='eventlet'
    return app
# project_dir/app.py,项目入口文件
from flaskr import creat_app, socketio

app = creat_app()

if __name__ == '__main__':
    socketio.run(app, '0.0.0.0', debug=True)

三,项目中使用

# flask路由中使用
@app.route('/set/')
def set():
    session['key'] = 'AAA'
    print(session.get('key'))
    return 'ok'

# flask-socketio事件中使用
@socketio.on('connect')
def do_connect():
    print(session.get('key'))
    session['key'] = 'BBB'
    print(session.get('key'))
    return 'ok'

# 着重点是在socketio事件中,使用getattr调用某类某方法过程中产生的会话,可以同样在flask路由中获取并做修改

参考:

Leave a Comment

Your email address will not be published.

*

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据