
本文介绍在 Django 中安全存储用户级敏感数据(如个人 API 密钥)的最佳实践,重点推荐使用 django-fernet-encrypted-fields 对字段进行应用层加密,并说明其使用方法、限制条件及关键注意事项。
本文介绍在 django 中安全存储用户级敏感数据(如个人 api 密钥)的最佳实践,重点推荐使用 `django-fernet-encrypted-fields` 对字段进行应用层加密,并说明其使用方法、限制条件及关键注意事项。
在 Django 应用中,为每位用户存储第三方服务的 API 密钥等敏感凭证时,绝不可明文保存于数据库。最稳妥的方案是在应用层对敏感字段进行强加密,并将密文持久化——即采用“应用级加密”(而非数据库透明加密或文件系统加密),确保即使数据库泄露,密钥仍无法被直接读取。
推荐使用社区维护成熟、遵循 Fernet 标准(基于 AES-128-CBC + HMAC)的第三方库:django-fernet-encrypted-fields(Jazzband 官方维护)。它通过 Django 字段封装自动完成加解密,集成简洁且安全性可靠。
✅ 快速集成示例
-
安装依赖:
pip install django-fernet-encrypted-fields
-
配置密钥(必须!)——在 settings.py 中添加:
# settings.py import base64 from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
推荐:使用 SECRET_KEY 衍生出 Fernet 密钥(生产环境请使用独立、高熵密钥)
def get_fernet_key(): kdf = PBKDF2HMAC( algorithm=hashes.SHA256(), length=32, salt=b"django-encrypted-fields-salt", iterations=480000, ) key = base64.urlsafe_b64encode(kdf.derive(SECRET_KEY.encode())) return key
ENCRYPTED_FIELD_KEYS = [get_fernet_key()]
> ⚠️ 注意:`ENCRYPTED_FIELD_KEYS` 是必需配置项,支持密钥轮换;首次部署后请妥善备份主密钥,丢失将导致数据永久不可解密。
3. 在模型中定义加密字段(以 `UserAPIKey` 为例):
```python
# models.py
from django.db import models
from django.contrib.auth.models import User
from encrypted_fields.fields import EncryptedTextField
class UserAPIKey(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='api_key')
key = EncryptedTextField() # 自动加密存储,读取时自动解密
def __str__(self):
return f"API key for {self.user.username}"
- 创建并访问密钥(完全透明):
# 创建 UserAPIKey.objects.create(user=request.user, key="sk_live_abc123...")
读取(返回明文字符串)
api_key = request.user.api_key.key # ✅ 自动解密,无需额外代码
### ⚠️ 关键限制与注意事项
- **查询能力受限**:加密操作发生在 Django 应用内存中,数据库仅存密文。因此:
- ❌ 不支持 `filter(key__contains=...)`、`filter(key='xxx')` 等基于明文的查询;
- ❌ 不可对 `EncryptedTextField` 设置 `db_index=True`、`unique=True` 或作为 `primary_key`;
- ✅ 若需高效检索,建议额外维护一个**不可逆哈希字段**(如 `key_hash = models.CharField(max_length=64, editable=False)`),使用 `hashlib.sha256(key.encode()).hexdigest()` 存储,用于 `filter(key_hash=...)` 快速定位。
- **密钥管理是核心**:Fernet 要求密钥保密且稳定。生产环境严禁硬编码或提交到版本库;推荐结合环境变量(如 `os.getenv('ENCRYPTION_KEY')`)或密钥管理服务(AWS KMS / HashiCorp Vault)动态加载。
- **审计与合规**:加密字段不替代权限控制。务必配合 Django 的认证/授权机制(如 `@login_required`、`user.has_perm`),确保仅授权用户可访问其密钥。
综上,`EncryptedTextField` 是 Django 生态中平衡安全性、易用性与可维护性的首选方案。只要严格遵循密钥管理规范、规避不支持的数据库特性,并辅以合理的哈希索引策略,即可稳健支撑多租户敏感数据隔离场景。大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











