python - 如何使用flask-login从数据库中注销用户

标签 python flask flask-login

我有一个用 python/flask 制作的 Web 应用程序,我使用 Flask-login 来验证用户身份。在用户界面中,用户可以注销。但用户也可以被数据库注销(当 session 过期时,或者当用户过期时)。

我的用户加载程序如下所示:

@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时,我希望用户注销。原因是:如果找不到 id,则无需多次调用 SessionUser.find_by_session_id。另外,我想显示一条用户已注销的消息(并且我只想显示一次)。最后,当用户从数据库注销时,我想使用未经身份验证的模板。

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

  1. 我无法闪烁消息“您已自动注销”(因为它会继续显示)
  2. 存在不必要的数据库命中。

我通过清除 session 变量 user_id 解决了这个问题,但这是一个不需要的解决方案,因为它使用 flask_login 的内部结构,而不是 API。

最好的方法是什么?

最佳答案

就像@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

以上回答了您的问题:

When the database can't find the id, I want the user to be logged out.

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

I want show a message the user has been logged out (and I only want to show this once)

以下是用户注销的方法:

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

这是一个正在运行的迷你应用程序,当用户注销时会闪烁一条消息:

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>

关于python - 如何使用flask-login从数据库中注销用户,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47670382/

相关文章:

python - 当模式被忽略时,使用 os.makedirs() 的最佳方法是什么

python - 动态计算一年中每周前 3 周的值

python - 使用 RandomizedSearchCV 在 sklearn 中进行超参数调整需要花费大量时间

python - 从 HTML 表单发布值并在 Flask View 中访问它们

python - 在 Flask View 中获取传递给 url_for 的 kwargs

python - 我是否正确阅读了这段特定的 Python 代码?

python - @login_manager.user_loader 从哪里获取用户 ID?

python - += 在 python 中有多个变量

python - Flask-Login 检查用户是否在没有装饰器的情况下通过身份验证

python - 在 Flask-Login token_loader 中加载 token 引发 "BadTimeSignature: timestamp missing"