如何用Pydantic赋值时转明文密码为bytes哈希并适配Beanie验证?
使用Pydantic自动哈希明文密码为bytes类型的问题
我希望通过Pydantic在赋值阶段,自动将明文字符串密码通过哈希函数转换为bytes类型的哈希值,但当前代码无法正常运行,最简示例如下:
import bcrypt from pydantic import BaseModel, field_validator def hash_password(password: str) -> bytes: return bcrypt.hashpw(password.encode('utf-8'), salt = bcrypt.gensalt()) class Password(BaseModel): hash_value: bytes @field_validator("hash_value") @classmethod def set_password(cls, plain_password: str) -> bytes: return hash_password(plain_password) class Settings: DEFAULT_PASSWORD = "my_plain_password" settings = Settings() password_doc = Password( hash_value = settings.DEFAULT_PASSWORD )
最初我错误地将hash_value声明为str类型,没注意到bcrypt.hashpw返回的是bytes类型,虽然能调用hash_password函数,但隐式类型转换会导致哈希密码失效。
现在的问题是:Pydantic期望hash_value是bytes类型,会先把字符串settings.DEFAULT_PASSWORD隐式转为bytes,再传入期望接收字符串的set_password方法,最终抛出错误:
Traceback (most recent call last): File "xxx", line 20, in <module> password_doc = Password( ^^^^^^^^^ File "xxx", line 176, in __init__ self.__pydantic_validator__.validate_python(data, self_instance=self) File "xxx", line 13, in set_password return hash_password(plain_password) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "xxx", line 5, in hash_password return bcrypt.hashpw(password.encode('utf-8'), salt = bcrypt.gensalt()) ^^^^^^^^^^^^^^^ AttributeError: 'bytes' object has no attribute 'encode'. Did you mean: 'decode'?
补充问题(编辑1)
感谢解答后大部分问题已解决,但发现set_password方法的调用次数超出预期。我使用Beanie Model存储关联Password文档的Config文档:
class Password(base.Password, Document): hash_value: bytes @field_validator("hash_value", mode="before") @classmethod def set_password(cls, plain_password: str | bytes) -> bytes: # 新的实现逻辑 class Config(base.Config, Document): password: Link[Password] def get_password(self) -> Link[Password]: return self.password
当执行models.Config.find_one(fetch_links=True)读取Config文档并获取关联链接时,set_password方法会被调用,此时传入的是存储的二进制哈希值,因此我需要在参数为二进制时直接返回该值。请问这是预期行为还是代码存在bug?
进一步说明(编辑2)
从数据库读取哈希密码时的二次验证应该是Beanie自动执行的,这很合理,因为数据库可能被外部修改。我原本不想让set_password方法接收二进制参数,但使用mode="before"后隐式转换不再发生,因此为了数据库验证需要允许参数为bytes类型。
内容的提问来源于stack exchange,提问作者DevilsThumb
相关产品推荐
相关产品推荐

