Django调用Fernet解密报TypeError:参数应为字节或ASCII字符串而非dict
报错原因分析
- Django ORM的
values()方法返回的是字典格式的QuerySet对象,而非passw字段的具体值。你直接将pw变量传入解密函数时,传递的是字典/QuerySet结构,不符合函数要求的字节/ASCII字符串参数类型。 - 结合报错栈来看,Fernet初始化时接收到的
key参数为字典类型,说明你调用decrypt_message时大概率传反了参数顺序:decrypt_message要求第一个参数为加密消息,第二个为解密密钥,如果把查询得到的pw传入了第二个参数位置,就会触发该报错。 - 额外排查点:你的查询代码中过滤条件写的是
emai=email,大概率是字段名拼写错误,正确应该为email=email,拼写错误会导致查询结果为空。
解决方案
- 修正查询代码,正确提取加密的密码字段值,推荐使用
values_list直接获取字段值:
# flat=True 直接返回字段值而非元组,first()取第一条匹配结果 pw = donator.objects.filter(email=email).values_list('passw', flat=True).first()
- 调用解密函数时严格按照参数顺序传参,示例如下:
# 参数1:加密后的密码,参数2:预先存储的Fernet解密密钥 decrypted_pw = decrypt_message(pw, your_fernet_secret_key)
- 如果你的密钥或者加密密码存储在数据库时为字符串格式,需要先编码为字节再传入解密逻辑,可修改解密函数兼容字符串类型输入:
def decrypt_message(encrypted_message,key): """ Decrypts an encrypted message """ # 兼容字符串类型的key,先转字节 if isinstance(key, str): key = key.encode('utf-8') f = Fernet(key) # 兼容字符串类型的加密消息,先转字节 if isinstance(encrypted_message, str): encrypted_message = encrypted_message.encode('utf-8') decrypted_message = f.decrypt(encrypted_message) return decrypted_message.decode()
内容的提问来源于stack exchange,提问作者nsb
相关产品推荐
相关产品推荐

