原理
flask-login使用的是客户端侧的session来存储用户的登录信息,在验证用户的登录状态时通过调用load_user(userid)用user的id来获得user对象,当通过id无法找到对应的user时即判定用户未登录。我们可以通过一个token来替换这个id,改写user的get_id()使其返回的是token,每次登录后更新user的token,load_user()时使用token来查找用户。当user在其他地点登录后token会被更新,这时load_user通过保存在session的旧的token值无法找到user,即判定登录失效,以实现单账号一个用户在线。
参考
https://flask-login.readthedocs.io/en/latest/#alternative-tokens
https://github.com/maxcountryman/flask-login/issues/155
示例
#使用sqlite3来当后台数据库表user三个字段id,name,aid DATABASE = r"F:project eportuser.db" #重写load_user失败时的方法使其跳转到/login,默认情况下只会返回401 @login_manager.unauthorized_handler def unauthorized(): # do stuff return redirect("/login") @login_manager.user_loader def load_user(userid): conn = sqlite3.connect(DATABASE) result = conn.execute("select name from user where aid =?", (userid,)).fetchall() if result: data=result[0][0] if data: return User(data, userid) return None class User(UserMixin): name = "test" id = "0000" def __init__(self, name, g_id): self.name = name self.id = g_id @app.route('/login', methods=["GET", "POST"]) def login(): if request.method == "GET": return render_template("login.html") username = request.form["username"] password = request.form["password"] if str(username) == "test" and str(password) == "test": flask.flash('login succeed') generated_id = str(int(time.time())) + username user = User("test", generated_id) conn = sqlite3.connect(DATABASE) conn.execute("update user set aid=? where name=?",(generated_id,username)) conn.commit() login_user(user) next = request.args.get("next") return flask.redirect('/') flask.flash('login failed') return render_template('login.html')