迁移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)
编写可复现最小代码示例的步骤
搭建基础环境
使用SQLite数据库(无需依赖外部服务),创建最小Flask应用,指定Python3.10环境,模拟Heroku栈22的运行环境。核心代码实现
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)触发错误的操作步骤
- 在Python3.10环境下安装依赖:
pip install flask flask-sqlalchemy flask-security bcrypt - 运行应用,尝试登录即可触发
TypeError: Unicode-objects must be encoded before hashing错误。如果本地环境原本正常,可先在Python3.6环境下创建用户,再将生成的数据库文件迁移到Python3.10环境中运行,更贴近真实场景。
- 在Python3.10环境下安装依赖:
内容的提问来源于stack exchange,提问作者YouWereOnceABeginner
相关产品推荐
相关产品推荐

