首页 > 解决方案 > 有没有办法使用 Flask Socket IO 登录用户?

问题描述

我将FlaskFlask SocketIOFlask Login一起使用。

我的问题是,当我尝试在事件中使用该login_user函数时socketio.on,没有错误,但用户没有登录。我的示例可能有助于说明这一点。my example event将被调用以供用户登录,然后/usersonly将在该事件被调用后被调用。

@socketio.on('my example event')
def my_func(json):
    ...
    login_user(user)

@app.route('/usersonly')
@login.user_required
def my_call():
    print(current_user)

我如何使它my_func可以登录用户?

标签: pythonflaskflask-loginflask-socketio

解决方案


Flask Login 不可能,因为在文档中,它说 Flask Login 使用 Cookie 或 Header 密钥进行身份验证,并且无法在 WebSocket(Socket IO)中访问它,所以我建议使用基于令牌的系统,如 API ,使用 JWT 令牌。

@socket.on('login')
def on_login(message):
    user = User.query.filter_by(email=message['email']).first()
    if not user:
       socket.emit('login', {'msg': "User not found"})

    if not user.check_password(form['password']):
       socket.emit('login', {'msg': "User not found"}) 
       return 
    user = UserSchema().dump(user).data
    token = jwt.encode(
            {'id': user['id'], 'user': user['name']})
    user['token'] = token.decode('UTF-8')
    socket.emit('login', {'user': user}) 

然后为登录创建一个装饰器:

def login_required(f):
    @wraps(f)
    def decorated(message):

        try:
            data = jwt.decode(message['token'], globals.current_app.config['SECRET_KEY'])
            try:
                user = User.query.filter_by(id=data['id']).first()
                Globals.current_user = UserSchema().dump(user).data
            except Exception as e:
                return Error.api_response(Error.USER_NOT_FOUND)
        except Exception as e:

            return Error.api_response(Error.INVALID_TOKEN)
        return f(message)

    return decorated

然后你可以像这样使用它:

@socketio.on('my example event')
@login_required
def my_func(json):
    ...

但是请记住,您需要始终在您的 socketio 中传递令牌,以进行服务器验证,我建议您阅读 Miguel Grinberh在烧瓶中休息 auth 的这篇博客


推荐阅读