Wii
Wii
发布于 2025-09-26 / 5 阅读
0
0

Django Model 保存敏感数据

在设计 Django Model 时,可能会遇到一些保存敏感字段的信息,比如密码、密钥等。

class TargetAuthInfo(models.Model):
    title = models.CharField("标题", max_length=200, default="未命名")
    address = models.CharField("地址", max_length=200, blank=True)
    endpoint = models.CharField("Endpoint", max_length=200, blank=True)
    username = models.CharField("用户名", max_length=200, blank=True)
    password = EncryptedField("密码", max_length=200, blank=True)

比如上面的 password 字段,需要保存节点的认证信息,如果明文保存的话,显然会存在严重的安全风险。

为了解决这个问题,可以使用加密算法对明文密码进行加密,通常加密算法还需要一个密钥,这个是解密数据的 Key,可以保存在环境变量或机器的某个位置,需要时读取。这样即便是数据库泄密,我们的敏感字段也不能被反解出来。

加密方式

在 Python 语言环境下,可以使用 cryptography 库。

from cryptography.fernet import Fernet
cipher = Fernet(FORNET_KEY)

cipher 对象提供加、解密的接口,至于 FORNET_KEY 后面会说。

Django Model 定义

结合 Django 框架,可以自定义一个加密字段,封装加密器,重写 get 和 set 方法。

from cryptography.fernet import Fernet

class EncryptedField(models.CharField):
    def __init__(self, *args, **kwargs):
        self.cipher = Fernet(settings.FORNET_KEY)
        super().__init__(*args, **kwargs)

    def get_prep_value(self, value):
        return self.cipher.encrypt(value.encode()).decode()

    def from_db_value(self, value, expression, connection):
        return self.cipher.decrypt(value.encode()).decode()

使用

class TargetAuthInfo(models.Model):
    title = models.CharField("标题", max_length=200, default="未命名")
    address = models.CharField("地址", max_length=200, blank=True)
    endpoint = models.CharField("Endpoint", max_length=200, blank=True)
    username = models.CharField("用户名", max_length=200, blank=True)
    password = EncryptedField("密码", max_length=200, blank=True)  # 使用自定义加密字段

生成 FORNET_KEY

前面说到,加密需要一个密钥,如果是使用 cryptography 的话,可以这样生成。

pip install cryptography
python
>>> from cryptography.fernet import Fernet
>>> key = Fernet.generate_key()
... print("Fernet Key:", key.decode())

示例。

wii 🌐 work misthub-server  main is 📦 v0.1.0 via 🐍 v3.10.13 ❯ poetry run pip install cryptography
The currently activated Python version 3.10.13 is not supported by the project (>=3.12).
Trying to find and use a compatible version. 
Using python3.13 (3.13.3)
Creating virtualenv misthub-server-qK9S8n11-py3.13 in /home/wii/.cache/pypoetry/virtualenvs
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
Collecting cryptography
  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/89/6b/09c30543bb93401f6f88fce556b3bdbb21e55ae14912c04b7bf355f5f96c/cryptography-46.0.1-cp311-abi3
-manylinux_2_34_x86_64.whl (4.6 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.6/4.6 MB 19.3 MB/s eta 0:00:00
Collecting cffi>=2.0.0 (from cryptography)
  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylin
ux2014_x86_64.manylinux_2_17_x86_64.whl (219 kB)
Collecting pycparser (from cffi>=2.0.0->cryptography)
  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.wh
l (118 kB)
Installing collected packages: pycparser, cffi, cryptography
Successfully installed cffi-2.0.0 cryptography-46.0.1 pycparser-2.23

[notice] A new release of pip is available: 25.1.1 -> 25.2
[notice] To update, run: pip install --upgrade pip
wii 🌐 work misthub-server  main is 📦 v0.1.0 via 🐍 v3.10.13 ❯ poetry run python                                                                    4s 
The currently activated Python version 3.10.13 is not supported by the project (>=3.12).
Trying to find and use a compatible version. 
Using python3.13 (3.13.3)
Python 3.13.3 (main, May  7 2025, 08:28:05) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from cryptography.fernet import Fernet
>>> key = Fernet.generate_key()
... print("Fernet Key:", key.decode())
... 
Fernet Key: u6C-TkZtfPnxdKFzU6AYX-Wjp5kI-m6GDzXI10hO5u8=
>>> 

这个 key 可放在项目的 settings 里面,新增一个 FORNET_KEY 字段。

FORNET_KEY='u6C-TkZtfPnxdKFzU6AYX-Wjp5kI-m6GDzXI10hO5u8='


评论