首页 > 解决方案 > 烧瓶登录 login_user 未设置 is_authenticated

问题描述

使用 Flask Login(第一次)并按照我遇到的每个教程示例,在正确发布凭据、调用 login_user() 并重定向到受保护的 login_required 路由后,我仍然收到 401 Unauthorized 响应。只有当我明确地将 is_authorised 属性设置为 True 时它才起作用。但这似乎应该是不必要的,而且我找不到任何教程示例可以做到这一点。我在看什么?下面的示例代码。谢谢!

from flask import Flask, render_template, url_for, jsonify, session, redirect, request
from flask_login import LoginManager, login_required, login_user, current_user

login_manager = LoginManager()
app = Flask(__name__)
app.secret_key = b'_5#y2L"F4Q8z\n\xecgwefweligli]/'
login_manager.init_app(app)

class User:
    _users = {
        'me': 'mypass'
    }

    _active_users = {}

    def __init__(self, user_id):
        self.user_id = user_id
        self.password = self._users[user_id]
        self._authenticated = False
        self._active = True

    @property
    def is_active(self):
        return self._active

    @property
    def is_authenticated(self):
        return self._authenticated

    @is_authenticated.setter
    def is_authenticated(self, value):
        if value:
            self._authenticated = True
        else:
            self._authenticated = False

    @property
    def is_anonymous(self):
        return False

    def get(user_id):
        if user_id in User._active_users:
            return User._active_users[user_id]
        if user_id in User._users:
            User._active_users[user_id] = User(user_id)
            return User._active_users[user_id]
        return None

    def get_id(self):
        return self.user_id

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

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        u = User.get(request.form['username'])
        app.logger.debug(u)
        if u and u.password == request.form['password']:
            app.logger.debug('authenticated')
            r = login_user(u)
            u.is_authenticated = True  # HERE: this shouldn't be necessary?
            app.logger.debug(u.is_authenticated)
            app.logger.debug(current_user.is_authenticated)
            return redirect(url_for('index'))
        return redirect(url_for('login'))
    return render_template('login.html')

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

当我删除:

u.is_authenticated = True

用户未通过身份验证。我查看了 login_user() 的源代码,它似乎没有设置 is_authenticated。我做对了吗?我只是感到困惑,因为没有文档/教程包含上述行,但都声称可以正常工作。

标签: pythonflaskflask-login

解决方案


您的原始代码需要显式设置 is_authenticated ,因为从一个请求到下一个请求,每次都会创建一个 User 对象的新实例,因此用户已经通过身份验证的信息会丢失。

为了避免丢失这些信息,我们需要一个地方来存储它。虽然 Flask-login 提供了一个 UserMixin 类来提供默认实现,但您可以在 User 模型中添加 authenticated 字段:

authenticated = db.Column(db.Boolean, default=False)

当用户登录时,您应该将authenticated 更改为true 并将更改保存在数据库中,当用户注销时,您应该将authentication 更改为false 并将更改保存在数据库中。

is_authenticated 函数将与此类似:

@property
def is_authenticated(self):
    return self.authenticated

请找到本教程


推荐阅读