Django非密码字段加密及订单数据安全存储相关问题咨询
可选存储方案说明
针对需要还原原始数据的敏感订单字段,不存在比加密更成熟、兼容性更高的安全存储方案,你可以搭配以下辅助方案进一步提升安全性:
- 字段级权限隔离:在Django模型层、数据库层分别配置敏感字段的访问权限,仅业务必要的服务账号可读取敏感字段,其他账号默认无访问权限
- 数据库透明加密(TDE):开启数据库层的静态加密能力,可防止物理磁盘被盗导致的数据泄露,该方案对业务代码无侵入,但无法应对数据库账号被非法获取后的拖库风险,需搭配应用层加密使用
- 敏感字段拆分存储:将订单敏感字段单独拆分到独立的数据表,和普通订单字段物理隔离,降低批量数据泄露的风险
1. 如何安全地对这类数据执行加密、解密操作?
不要自行实现加密逻辑,直接使用Django生态内经过社区验证的加密字段库即可,推荐使用django-cryptography或者django-fernet-fields,二者均基于标准Fernet加密算法实现,符合AES-128-CBC加密标准,自带完整性校验,使用时仅需要替换模型字段的声明方式,不需要额外处理加解密逻辑,示例代码如下:
from django.db import models from django_cryptography.fields import encrypt class Order(models.Model): order_id = models.CharField(max_length=32, unique=True) # 非敏感字段不需要加密 pay_status = models.IntegerField(default=0) create_time = models.DateTimeField(auto_now_add=True) # 敏感字段用encrypt装饰器包裹即可 goods_detail = encrypt(models.JSONField()) purchase_count = encrypt(models.IntegerField()) total_amount = encrypt(models.DecimalField(max_digits=10, decimal_places=2))
加解密操作注意事项:
- 仅加密必要的敏感字段,避免全字段加密带来的性能损耗,也不影响普通字段的查询效率
- 解密操作仅在业务需要使用明文的场景触发,不要在全量列表查询等接口中返回敏感字段的明文
- 所有加解密操作均在应用层执行,不要将密钥传递到数据库层,避免数据库日志泄露密钥
2. 加密密钥应该在什么位置、以何种方式存储?
绝对禁止将密钥硬编码在业务代码中、或者写入配置文件提交到代码仓库,正确的存储方式按部署场景区分:
- 本地开发环境:密钥存储在本地
.env文件中,将.env加入.gitignore规则,禁止提交到代码仓库 - 生产环境:
- 云部署场景直接使用云厂商的密钥管理服务(KMS)存储主密钥,应用启动时通过权限校验临时拉取密钥,不需要将密钥持久化存储在应用服务器本地
- 自建部署场景将密钥存储在独立的权限受控的配置中心,仅授权应用服务器IP可读取密钥配置,不要在服务器本地的环境变量、配置文件中持久化存储密钥
- 密钥访问权限做最小化控制,仅应用核心服务进程有读取权限,运维人员默认不开放密钥查看权限
3. 是否只需要使用单一主密钥即可?
不建议仅使用单一主密钥,推荐采用两层密钥架构:
- 上层为根密钥(主密钥):仅用于加密下层的数据密钥,不直接参与业务数据加密,存储在KMS或独立加密机中,应用侧不存储根密钥
- 下层为数据密钥:用于实际加密业务字段,可按业务线、时间周期或者数据量级(如每10万条订单)生成新的数据密钥,加密后的数据密钥和业务密文存储在一起
解密时先调用KMS用根密钥解密拿到数据密钥,再用数据密钥解密业务密文即可。两层密钥架构的优势是密钥轮换成本极低:如果单个数据密钥泄露,仅需要重新加密对应范围内的业务数据即可;如果根密钥需要轮换,仅需要重新加密所有数据密钥,不需要改动历史业务密文。如果你的业务规模极小,年订单量低于10万,也可以暂时使用单一主密钥,但需要提前预留密钥轮换的技术方案。
内容的提问来源于stack exchange,提问作者wijaya firhan
相关产品推荐
相关产品推荐

