如何使用flask-login

时间:2017-12-06 09:01:36

标签: python flask flask-login

我有一个用python / flask制作的web应用程序,我使用flask-login来验证用户。在用户界面中,用户可以注销。但是,用户也可以通过数据库注销(当会话过期时或用户过期时)。

我的用户加载器如下所示:

@login_manager.user_loader
def user_loader(id):
    user = SessionUser.find_by_session_id(id) #hits the database
    if user is None:
        flash('You have been automatically logged out')
        #flask_login.logout_user() #RecursionError: maximum recursion depth exceeded
        session['user_id'] = None
    return user

当数据库找不到id时,我希望用户退出。原因是:如果无法找到SessionUser.find_by_session_id,则无需多次拨打id - 来电。此外,我想显示用户已注销的消息(我只想显示一次)。最后,当用户退出数据库时,我想要使用未经身份验证的模板。

如果我没有if user is None:代码,那么每次请求都会遇到用户加载程序。这有两个问题:

  1. 我无法刷新消息"您已自动退出" (因为它会继续显示)
  2. 有一个不必要的数据库命中。
  3. 我通过清除会话变量user_id来解决此问题,但这是一个不受欢迎的解决方案,因为它使用的是flask_login的内部,而不是API。

    最好的方法是什么?

2 个答案:

答案 0 :(得分:2)

就像@Sraw说的那样,不要从user_loader手动注销用户。这应该只返回用户的给定ID或None

@login_manager.user_loader
def user_loader(user_id):
    return SessionUser.find_by_session_id(user_id)  # hits the database

以上回答你的问题:

  

当数据库找不到id时,我希望用户注销。

现在,回答你的第二个问题:

  

我想要显示用户已注销的消息(我只想   显示一次)

以下是用户注销的方式:

  1. user_id不在您的数据库中(用户已被删除)
  2. user_id不在用户的浏览器Cookie会话中(尚未登录或清除其Cookie)
  3. 您致电flask_login.logout_user,从user_id
  4. 删除了session

    这是一个可以在用户注销时闪烁消息的迷你应用程序:

    from flask import current_app as app, flash, redirect, render_template, session
    from flask_login import login_manager, login_required, logout_user
    
    
    @login_manager.user_loader
    def user_loader(user_id):
        return SessionUser.find_by_session_id(user_id)
    
    
    @app.route('/logout')
    @login_required
    def logout():
        logout_user()
        if session.get('was_once_logged_in'):
            # prevent flashing automatically logged out message
            del session['was_once_logged_in']
        flash('You have successfully logged yourself out.')
        return redirect('/login')
    
    
    @app.route('/login', methods=['GET', 'POST'])
    def login():
        if app.current_user.is_authenticated:  # already logged in
            return redirect('/home')
        if request.method == 'POST':
            user = SessionUser.find_by_session_id(request.data['user_id'])
            if user:
                login_user(user)
                session['was_once_logged_in'] = True
                return redirect('/home')
            flash('That user was not found in the database.')
        if session.get('was_once_logged_in'):
            flash('You have been automatically logged out.')
            del session['was_once_logged_in']
        return render_template('/login.html')
    
    
    @app.route('/home')
    @login_required
    def home():
        return 'You are logged in as {0}.'.format(app.current_user.id)
    

    login.html的内容:

    {% with messages = get_flashed_messages() %}
      {% if messages %}
        <ul class=flashes>
        {% for message in messages %}
          <li>{{ message }}</li>
        {% endfor %}
        </ul>
      {% endif %}
    {% endwith %}
    
    <form method="post">
      User ID: <input type="text" name="user_id" /><br />
      <button type="submit">Login</button>
    </form>
    

答案 1 :(得分:0)

如果用户的会话已在数据库中过期,我认为您不需要手动注销用户。

检查this

正如您所看到的,如果user_loader返回None,则表示此用户无效,因此将从当前会话中移除该用户,与logout相同。所以你需要做的只是return SessionUser.find_by_session_id(id)

更新

以下代码段应该可以正常运行。如果没有,可能还有其他错误。

@login_manager.user_loader
def user_loader(id):
    # print(id)  # try printing current user's id to check.
    user = SessionUser.find_by_session_id(id) #hits the database
    if user is None:
        flash('You have been automatically logged out')
    return user