使用 python flask-login 登录循环

login loop with python flask-login

我正在学习使用 flask-login class。这是一个介绍 class,我们没有在本练习中使用数据库,而是将凭据(散列)存储在 resing 文件中。我能够验证用户凭据,但是当用户 'successfully' 登录时,我没有重定向到受保护的 URL,而是被重定向到登录页面。 代码: 用户模型:

class User(UserMixin):

    def __repr__(self):
        return '<User{}>'.format(self)

    def __init__(self):
        self.username = None
        self.email = None
        self.password = None
        self.user_id = None

    def get_id(self):
        return self.user_id

登录管理器:

login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = "login"


@login_manager.user_loader
def load_user():
    return User

登录部分:

user = User()
login_user(user)
return redirect(url_for('main'))

在我阅读的所有教程中,都使用了 sql 数据库。因为我们没有使用它,并且因为我根本不需要登录用户是特定的 - 只是为了通过身份验证,所以我正在阅读的很多内容在参数范围内都是行不通的。

您在定义用户加载器时忘记了一些东西。该函数采用 user_id 参数和 returns class 用户的对象,而不是 class 本身。 (参见 documentation

下面的简化示例向您展示了不使用数据库实现的可能性。

基本上,flask-login 将用户对象的属性 id 存储在会话 cookie 中。基于此 id,相应的用户由数据库中的 LoginManager 查询,此处已由 class 变量/列表 users.
替换 数据库实现通常有一个 id 列,它被定义为对于条目是唯一的。在示例中,唯一的 id of the object 用作替代。这意味着 mixin 的 getter 将被覆盖。所以这个例子保留了一个创建的用户对象的列表。在这些用户中可以通过他们的 ID 或用户名找到。

烧瓶 (app.py)
from flask import (
    Flask,
    redirect,
    render_template,
    request,
    url_for
)
from flask_login import (
    LoginManager,
    UserMixin,
    login_required,
    login_user,
    logout_user
)

class User(UserMixin):
    def __init__(self, username, password):
        self.username = username
        self.password = password
        self.__class__.users.append(self)

    def get_id(self):
        return id(self)

    users = []

    @classmethod
    def get(cls, user_id):
        for usr in cls.users:
            if usr.get_id() == user_id:
                return usr
        return None

    @classmethod
    def find_by_username(cls, username):
        for usr in cls.users:
            if usr.username == username:
                return usr
        return None

app = Flask(__name__)
app.secret_key = 'your secret here'

login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'

@login_manager.user_loader
def load_user(user_id):
    return User.get(user_id)

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/register', methods=['GET', 'POST'])
def register():
    keys = ('username', 'password')
    if request.method == 'POST' and all(k in request.form for k in keys):
        username = request.form['username']
        password = request.form['password']
        if User.find_by_username(username) is None:
            User(username, password)
            return redirect(url_for('.login'))
    return render_template('register.html')

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        user = User.find_by_username(username)
        if user and user.password == password:
            login_user(user)
            return redirect(request.args.get('next', url_for('.index')))
    return render_template('login.html')

@app.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect(url_for('.index'))

@app.route('/secret')
@login_required
def secret():
    return 'You found the secret.'
HTML (templates/index.html)
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Index</title>
  </head>
  <body>
    {% if current_user.is_authenticated -%}
    <a href="{{ url_for('logout') }}">Logout</a>
    {% else -%}
    <a href="{{ url_for('register') }}">Register</a> |
    <a href="{{ url_for('login') }}">Login</a>
    {% endif -%}
    <h1>Index</h1>
    {% if current_user.is_authenticated -%}
    Welcome {{ current_user.username }}!
    {% else -%}
    Welcome Guest!
    {% endif -%}
  </body>
</html>
HTML (templates/login.html)
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Login</title>
  </head>
  <body>
    <a href="{{ url_for('register') }}">Register</a>
    <h1>Login</h1>
    <form method="post">
      <input type="text" name="username" placeholder="username" />
      <input type="password" name="password" placeholder="password" />
      <input type="submit" />
    </form>
  </body>
</html>
HTML (templates/register.html)
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Register</title>
  </head>
  <body>
    <h1>Register</h1>
    <form method="post">
      <input type="text" name="username" placeholder="username" />
      <input type="password" name="password" placeholder="password" />
      <input type="submit" />
    </form>
  </body>
</html>