我有一个用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:
代码,那么每次请求都会遇到用户加载程序。这有两个问题:
我通过清除会话变量user_id
来解决此问题,但这是一个不受欢迎的解决方案,因为它使用的是flask_login
的内部,而不是API。
最好的方法是什么?
答案 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时,我希望用户注销。
现在,回答你的第二个问题:
我想要显示用户已注销的消息(我只想 显示一次)
以下是用户注销的方式:
user_id
不在您的数据库中(用户已被删除)user_id
不在用户的浏览器Cookie会话中(尚未登录或清除其Cookie)flask_login.logout_user
,从user_id
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