FastAPI切换PostgreSQL后bcrypt验证密码报错:str无法转PyBytes
问题:FastAPI切换PostgreSQL后生成Token时bcrypt验证报错
错误信息
return bcrypt.checkpw(password=password_byte_enc, hashed_password=hashed_password) TypeError: argument 'hashed_password': 'str' object cannot be converted to 'PyBytes'
相关代码
def get_password_hash(password): # return bcrypt_context.hash(password) pwd_bytes = password.encode('utf-8') salt = bcrypt.gensalt() hashed_password = bcrypt.hashpw(password=pwd_bytes, salt=salt) return hashed_password def verify_password(plain_password, hashed_password): password_byte_enc = plain_password.encode('utf-8') return bcrypt.checkpw(password=password_byte_enc, hashed_password=hashed_password)
问题原因
SQLite支持直接存储bytes类型数据,但PostgreSQL会自动将bytes转为字符串类型存储。而bcrypt的checkpw方法要求hashed_password参数必须是bytes类型,读取数据库中的字符串哈希值传入时就会触发类型错误。
解决办法
方案一:修改验证函数,转换哈希密码类型
在verify_password中判断哈希密码的类型,若为字符串则转为bytes:
def verify_password(plain_password, hashed_password): password_byte_enc = plain_password.encode('utf-8') # 将字符串类型的哈希密码转为bytes if isinstance(hashed_password, str): hashed_password = hashed_password.encode('utf-8') return bcrypt.checkpw(password=password_byte_enc, hashed_password=hashed_password)
方案二:统一哈希密码的存储格式
修改get_password_hash函数,将生成的bytes哈希转为字符串后再存入数据库,验证时再转回bytes:
def get_password_hash(password): pwd_bytes = password.encode('utf-8') salt = bcrypt.gensalt() hashed_password = bcrypt.hashpw(password=pwd_bytes, salt=salt) # 将bytes哈希转为字符串格式存储 return hashed_password.decode('utf-8')
对应更新verify_password:
def verify_password(plain_password, hashed_password): password_byte_enc = plain_password.encode('utf-8') # 把字符串哈希转回bytes hashed_password_bytes = hashed_password.encode('utf-8') return bcrypt.checkpw(password=password_byte_enc, hashed_password=hashed_password_bytes)
方案三:调整数据库字段类型
将存储哈希密码的字段类型改为BYTEA,确保数据库直接存储bytes数据,读取时保持bytes类型,无需额外转换。此方案需要同步调整数据写入逻辑,确保存入的是bytes类型。
内容的提问来源于stack exchange,提问作者k1dr0ck
相关产品推荐
相关产品推荐

