我有一个用 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:
代码,则每个请求都会遇到用户加载程序。这有两个问题:
- 我无法闪烁消息“您已自动注销”(因为它会继续显示)
- 存在不必要的数据库命中。
我通过清除 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)
以下是用户注销的方法:
user_id
不在您的数据库中(该用户已被删除)user_id
不在用户的浏览器 Cookie session 中(尚未登录,或清除其 Cookie)- 您调用了
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/