【发布时间】:2021-06-04 13:29:00
【问题描述】:
我正在尝试使用 Fernet 创建一个 django 自定义加密字段。我发现自动执行此操作的库似乎已过时/与 Django>3.0
不兼容在this thread我找到了如下代码:
import base64
from django.db.models import CharField
from cryptography.fernet import Fernet
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from core import settings
class SecureString(CharField):
salt = bytes(settings.SECURE_STRING_SALT, encoding="raw_unicode_escape")
kdf = PBKDF2HMAC(algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000,
backend=default_backend())
key = base64.urlsafe_b64encode(kdf.derive(settings.SECRET_KEY.encode('utf-8')))
f = Fernet(key)
def from_db_value(self, value, expression, connection):
return str(self.f.decrypt(value), encoding="raw_unicode_escape")
def get_prep_value(self, value):
return self.f.encrypt(bytes(value, encoding="raw_unicode_escape"))
它似乎适用于编码部分(如果我使用管理程序检查数据库字段,内容显示为一种汉字),但不适用于解码。
每次我在 Admin 中保存记录时,都会触发此错误(虽然保存在数据库中):
raise TypeError("{} must be bytes".format(name)) TypeError: token must 是字节
由于get_prep_value 代码,不应该在数据库记录中已经是字节吗?尝试在 admin 中列出记录(访问读取功能)时也会发生同样的错误。
我该如何解决这个问题?我使用 SQL Server 作为数据库(以防它可能相关)。
【问题讨论】:
-
get_prep_value是否返回str或bytes对象?你可能需要.encode()它 -
另外,请不要使用大写标题:)
-
为标题道歉。根据库文档,加密方法已经返回字节,描述为“fernet token”。
-
您使用的是自定义字段,对吗?
SecureString在您的代码库中吗?只需将.encode()放在get_prep_value的返回值的末尾 -
不起作用,即使我之前将返回的字节对象转换为字符串。
标签: python-3.x django cryptography field fernet