跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

如何在 Django 应用中安全存储用户专属敏感数据

本文介绍在 django 中安全存储用户级敏感数据(如第三方 api 密钥)的最佳实践,重点推荐使用 django-fernet-encrypted-fields 对数据库字段进行应用层透明加密,并说明其使用限制与关键注意事项。 本文介绍在 django 中安全存储用户级 敏感数据 (如第三方 api 密钥)的最佳实践,重点推荐使用 django-fernet-encrypted-fields 对数据库字段进行应用层透明加密,并说明其使用限制与关键注意事项。 在 Django 应用中,为每位用户关联并安全存储第三方服务的 API 密钥,是一项常见但高风险的需求。直接明文存储于数据库严重违背最小权限与数据保密原则;而将密钥交由客户端或环境变量管理又无法实现“按用户隔离”。 最合理且被广泛验证的方案是:在 Django 应用层对敏感字段执行对称加密(如 Fernet),再将密文持久化至数据库。 推荐使用由 Jazzband 维护的成熟第三方库 django-fernet-encrypted-fields 。它基于 Python 标准库 cryptography 实现 AES-128-CBC 加密,自动处理密钥派生、随机 IV 生成与认证标签(AEAD),确保机密性与完整性。 ✅ 快速集成示例 首先安装:
pip install django-fernet-encrypted-fields
在 settings.py 中配置主密钥( 必须严格保密,禁止提交至版本控制 ): Python 网站开发之Django环境搭建 WORD版 本文档主要讲述的是Python 网站开发之Django环境搭建;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看 下载
# settings.py import os from cryptography.fernet import Fernet # 推荐:从环境变量读取(如 Docker secrets 或 .env) ENCRYPTION_KEY = os.environ.get('DJANGO_ENCRYPTION_KEY') if not ENCRYPTION_KEY: # 开发时可生成临时密钥(生产环境务必替换!) ENCRYPTION_KEY = Fernet.generate_key().decode()
定义模型(关联到 User 或自定义用户扩展模型):
# 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}"
使用时如同普通字段:
# views.py 或业务逻辑中 from django.contrib.auth.decorators import login_required from django.shortcuts import get_object_or_404 @login_required def fetch_external_data(request): api_key_obj = get_object_or_404(UserAPIKey, user=request.user) raw_api_key = api_key_obj.key # 自动解密,返回 str 类型明文 # → 调用第三方服务...
⚠️ 关键限制与注意事项(务必遵守) 查询能力受限 :加密在 Django 应用层完成,数据库仅存储密文。因此 无法对 EncryptedTextField 执行 filter()、exclude()、__icontains 等查询操作 ——所有匹配必须先加载对象再在内存中比对(极低效,不推荐)。 禁止添加数据库约束 :该字段 不可设为 primary_key、unique=True、db_index=True ,也不应参与 ORDER BY 或 GROUP BY。违反将导致数据不一致或查询失败。 密钥安全管理 :ENCRYPTION_KEY 是解密唯一凭证。生产环境必须通过安全方式注入(如 Kubernetes Secret、AWS SSM Parameter Store), 绝不可硬编码或写入 Git 。 备份与迁移 :数据库备份包含密文,但恢复时必须确保 ENCRYPTION_KEY 完全一致,否则所有密钥永久丢失。 替代方案权衡 :若需高频模糊搜索或索引查询,应考虑将非敏感标识符(如哈希后 token ID)存于数据库,密钥本身托管至专用密钥管理服务(如 HashiCorp Vault、AWS KMS),通过短期令牌动态获取——但这会增加架构复杂度。 综上,EncryptedTextField 是 Django 生态中平衡安全性、易用性与合规性的首选方案。只要明确其设计边界(即“仅支持精确读取,不支持数据库侧查询”),即可稳健支撑用户级密钥管理场景。

相关文章