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

迁移Heroku栈至22后登录功能出现bcrypt编码类型错误求助

解决办法
  • 升级依赖版本
    旧版Flask-Security在Python3.8+环境下存在字符串编码兼容问题,直接升级到最新稳定版:pip install --upgrade flask-security,同时同步升级bcrypt:pip install --upgrade bcrypt,多数情况下这就能解决问题。

  • 显式处理密码编码
    不用修改数据库字段类型,在User模型的密码设置逻辑里,把字符串转成bytes再传给加密方法:

    from flask_security import hash_password
    
    class User(UserMixin, db.Model):
        password = db.Column(db.String(255))
    
        def set_password(self, password):
            # 强制转成utf-8编码的bytes
            self.password = hash_password(password.encode('utf-8'))
    

    如果用的是@password.setter装饰器,同样在内部添加编码步骤。

  • 兼容旧密码数据
    之前Python3.6存储的密码可能是未编码的字符串,登录验证时可以添加兼容逻辑:

    from flask_security import verify_password
    
    def custom_verify_password(password, user):
        # 先尝试直接验证,失败则编码后再试
        if verify_password(password, user.password):
            return True
        return verify_password(password.encode('utf-8'), user.password)
    
    # 替换默认的验证函数
    security = Security(app, user_datastore, verify_password=custom_verify_password)
    
编写可复现最小代码示例的步骤
  1. 搭建基础环境
    使用SQLite数据库(无需依赖外部服务),创建最小Flask应用,指定Python3.10环境,模拟Heroku栈22的运行环境。

  2. 核心代码实现

    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    from flask_security import Security, UserMixin, RoleMixin, SQLAlchemyUserDatastore, auth_required
    
    app = Flask(__name__)
    app.config['SECRET_KEY'] = 'super-secret'
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
    app.config['SECURITY_PASSWORD_HASH'] = 'bcrypt'
    app.config['SECURITY_PASSWORD_SALT'] = 'your-salt-string'
    
    db = SQLAlchemy(app)
    
    # 用户-角色关联表
    roles_users = db.Table('roles_users',
        db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
        db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))
    
    class Role(db.Model, RoleMixin):
        id = db.Column(db.Integer(), primary_key=True)
        name = db.Column(db.String(80), unique=True)
    
    class User(db.Model, UserMixin):
        id = db.Column(db.Integer, primary_key=True)
        email = db.Column(db.String(255), unique=True)
        password = db.Column(db.String(255))
        active = db.Column(db.Boolean())
        roles = db.relationship('Role', secondary=roles_users, backref=db.backref('users', lazy='dynamic'))
    
    user_datastore = SQLAlchemyUserDatastore(db, User, Role)
    security = Security(app, user_datastore)
    
    # 测试登录路由
    @app.route('/')
    @auth_required()
    def home():
        return "Logged in successfully"
    
    if __name__ == '__main__':
        with app.app_context():
            db.create_all()
            # 模拟旧环境创建的用户(直接传入字符串密码)
            if not user_datastore.find_user(email='test@example.com'):
                user_datastore.create_user(email='test@example.com', password='test123', active=True)
                db.session.commit()
        app.run(debug=True)
    
  3. 触发错误的操作步骤

    • 在Python3.10环境下安装依赖:pip install flask flask-sqlalchemy flask-security bcrypt
    • 运行应用,尝试登录即可触发TypeError: Unicode-objects must be encoded before hashing错误。如果本地环境原本正常,可先在Python3.6环境下创建用户,再将生成的数据库文件迁移到Python3.10环境中运行,更贴近真实场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 09:36:25