You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask-Login登录成功后认证状态失效问题求助

Flask-Login登录后立即判定未认证问题

使用Flask、Flask-Login和Flask-SQLAlchemy开发Web应用,已实现注册、登录和邮箱确认功能。登录时日志显示“用户已登录”,但重定向到首页后系统立即判定用户未认证,使用正确凭证登录也无法解决该问题。

以下是简化代码:

User模型

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), index=True, unique=True, nullable=False)
    profile_image = db.Column(db.String(255), nullable=True, default='default.jpg')  # 用户照片路径
    email = db.Column(db.String(120), index=True, unique=True, nullable=False)
    email_confirmed = db.Column(db.Boolean, default=False)
    confirmation_code = db.Column(db.String(64), nullable=True)
    confirmation_sent_at = db.Column(db.DateTime, nullable=True)
    password_hash = db.Column(db.String(128))
    phone = db.Column(db.String(20), unique=True, nullable=False)
    first_name = db.Column(db.String(64), nullable=False)
    last_name = db.Column(db.String(64), nullable=False)
    date_of_birth = db.Column(db.Date)
    gender = db.Column(db.String(10))
    address = db.Column(db.String(255))
    is_active = db.Column(db.Boolean, default=True)
    role = db.Column(db.String(64), default='user')
    login_attempts = db.Column(db.Integer, default=0)
    lock_until = db.Column(db.DateTime, nullable=True)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
    
    # 通过purchases表建立与课程的关联
    courses = db.relationship('Course', secondary=purchases, lazy='subquery',
                              backref=db.backref('users', lazy=True))

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

    def set_password(self, password):
        password_bytes = password.encode('utf-8')
        salt = bcrypt.gensalt()
        self.password_hash = bcrypt.hashpw(password_bytes, salt).decode('utf-8')

    def check_password(self, password):
        password_bytes = password.encode('utf-8')
        return bcrypt.checkpw(password_bytes, self.password_hash.encode('utf-8'))
    
    def increment_login_attempts(self):
        self.login_attempts += 1
        db.session.commit()

    def reset_login_attempts(self):
        self.login_attempts = 0
        db.session.commit()

    def lock_account(self):
        self.lock_until = datetime.utcnow() + timedelta(minutes=10)  # 锁定10分钟
        db.session.commit()

    def is_account_locked(self):
        return self.lock_until is not None and self.lock_until > datetime.utcnow()

    def activate_user(self):
        self.is_active = True
        db.session.commit()

    def deactivate_user(self):
        self.is_active = False
        db.session.commit()

    def confirm_email(self):
        self.email_confirmed = True
        db.session.commit()

登录路由

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

@app.route('/login', methods=['GET', 'POST'])
def login():
    if current_user.is_authenticated:
        return redirect(url_for('index'))
    form = LoginForm()
    if form.validate_on_submit():
        # 将用户筛选条件从email改为username
        user = User.query.filter_by(username=form.username.data).first()
        if user and not user.is_account_locked():
            if user.check_password(form.password.data):
                if user.email_confirmed:
                    print(f'用户"{user.username}"已登录。')
                    user.reset_login_attempts()  # 成功登录后重置尝试次数
                    next_page = request.args.get('next')
                    login_user(user)
                    return redirect(next_page) if next_page else redirect(url_for('index'))
                else:
                    flash('请先确认您的账户再登录。', 'warning')
            else:
                user.increment_login_attempts()
                if user.login_attempts >= 10:
                    user.lock_account()
                    flash('您的账户因多次登录失败被临时锁定。', 'danger')
                else:
                    flash('用户名或密码错误。', 'danger')
        else:
            flash('账户已锁定,请稍后再试。', 'danger')
    return render_template('auth/login.html', title='登录', form=form)

init.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from flask_mail import Mail
from app.config import Config
from flask_bcrypt import Bcrypt

app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)

app.secret_key = 'ovrewu5t2utu4orhwergewhirghweorghd87827d283t4h2od4`d8`73nfro'

login_manager = LoginManager()

bcrypt = Bcrypt(app)

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

mail = Mail(app)

from app.auth.routes import *
from app.profile.routes import *

已尝试的解决方法:

  • 确认Flask应用已设置SECRET_KEY
  • 验证login_user调用时传入了正确的用户对象
  • 检查数据库中用户存在且处于激活状态
  • 排查Flask的会话管理和Cookie设置相关问题

内容的提问来源于stack exchange,提问作者John Snow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 14:47:10