簡體   English   中英

Flask-Socketio 與 Flask-Login 的 current_user 不同步

[英]Flask-Socketio out of sync with Flask-Login's current_user

Python==3.8.5
Flask==1.1.2
Flask-SocketIO=4.3.0 (also tried 4.3.1)
Flask_Login=0.4.1

我將 gevent 與 Gunicorn 一起使用

gunicorn -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker w 1 wsgi:server

我已經使用 Flask-Login 幾年了,大約一年來,我設法讓它作為帶有 React 前端的 RESTful 應用程序的身份驗證機制。 我遇到的問題在於 Flask-socketio 的使用。 雖然我成功注銷,但flask_socketio端點中的current_user仍然保持current_user對象有效,更奇怪的是當我用另一個用戶重新登錄時,全局Flask應用程序中的current_user反映了注銷和新登錄,但是 flask_socketio 中的 current_user 與更改失去同步。 我已經搜索了很長一段時間,我找到了 Flask_socketio 的作者 Miguel Grinberg 的一篇博客文章,他指出:

Flask 會話在 Socket.IO 連接時復制到 Socket.IO 會話。 在建立 Socket.IO 連接后對 Flask 路由中的會話所做的更改將無法在 Socket.IO 會話上訪問。 在 Socket.IO 事件處理程序中對會話所做的更改將無法在 Flask 用戶會話上訪問。

Flask 登錄支持:您可以毫無問題地在 Socket.IO 事件處理程序中引用 current_user。

的確,我可以從 socket.io 引用和訪問 current_user,但它始終是初始值,並不能反映它在其生命周期中可能受到的更改。

我可以在 socket.io 上下文中以某種方式訪問​​整個應用程序(包括常規 http 請求)中可訪問的 current_user 嗎?

這是一個常規的 http 示例:

@auth_bp.route('/current_user/<int:id>')
def user_is_authenticated(id):
    if id:
        if current_user.is_authenticated:
            if current_user.id == int(id):
                return {
                            "code": 200,
                            "authenticated": True,
                            "message":"User is logged-in", 
                            "user": user_schema.dump(current_user),
                        }, 200
    return {
                "code": 400,
                "authenticated": False,
                "message":"Either user id missing or you are not authenticated.", 
                "user": None
            }, 400

如果我從客戶端點擊上述端點,我會得到實際的current_user。 下面是用於相同目的的 socketio 端點:

@socket.on('getCurrentUser', namespace='/auth')
def user_is_authenticated(data):
    id = data.get('id')
    if id:
        if current_user.is_authenticated:
            if current_user.id == int(id):
                user = user_schema.dump(current_user)
                emit('currentUser', {'user': user, 'room': user.room}, room=user.room)
    #emit event here to sid

模擬身份驗證操作

#login as Adam Clark

current_user across Flask now is {
    fullname: 'Adam Clark',
    other_fields: 'data'
}

current_user in socketio context also is {
    fullname: 'Adam Clark',
    other_fields: 'data'
}

# logout

current_user across Flask now is AnonymousUser

current_user in socketio context also is still {
    fullname: 'Adam Clark',
    other_fields: 'data'
}


# login as John Wild

current_user across Flask now is {
    fullname: 'John Wild',
    other_fields: 'data'
}

current_user in socketio context also is still {
    fullname: 'Adam Clark',
    other_fields: 'data'
}

兩者結果之間的唯一區別是 http 一個(Flask 端點)反映了 current_user 的當前狀態,而 socket.io 僅維護對象的初始狀態。

在使用基於 cookie 的會話和 Socket.IO 時,這是一個不幸的限制。 問題是,如果 HTTP 路由對會話進行了更改(例如使用 Flask-Login 注銷),則無法告訴 WebSocket 連接會話 cookie 已更改,因為 WebSocket 不支持 cookie在初始連接請求之外。

文檔鏈接: https : //flask-socketio.readthedocs.io/en/latest/#access-to-flask-s-context-globals

如果您需要在 HTTP 和 WebSocket 端之間同步會話,請使用服務器端會話。 Flask-Session 擴展是一個不錯的選擇。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM