作者:赖铭
导语:出于安全考虑,一些敏感信息是需要加密存入数据库的。这样即使被黑客脱库,也能最大限度的避免损失。
数据加密并不是难事,各种现成的加密库可以轻松实现高强度的加密。对于加密标准的选择,根据实际场景需要,在《IDC开发运维安全标准》 4.1算法标准 中选择合适算法即可。
在实际开发中,我是在业务现成逻辑代码已经大体完成时接手,被要求将部分字段加密处理的。因此,我希望加密逻辑对业务逻辑完全不可见,做到不需要修改任何业务逻辑代码,即可接入数据加密。
要做到对业务逻辑不可见,就需要在字段入库和出库时,自动进行加密和解密。Django的自定义Field提供的一些接口,可以在数据出库后、数据入库前,做一些特定的操作。如:DatetimeField,就是使用了这些接口,做到了可以直接使用python的datetime进行操作,免去了与数据库类型转换的工作。
下面这个例子,选择的是AES对称加密算法,对CharField进行加密处理。
class AESCharField(models.CharField):
"""
在数据库中AES256加密的 CharField
- 兼容未加密数据,加密后字符串会带上
"""
def __init__(self, *args, **kwargs):
"""
初始化
:param prefix: 加密串前缀
"""
if 'prefix' in kwargs:
self.prefix = kwargs['prefix']
del kwargs['prefix']
else:
self.prefix = "aes_str:::"
self.cipher = AESCipher(settings.SECRET_KEY)
super(AESCharField, self).__init__(*args, **kwargs)
def deconstruct(self):
name, path, args, kwargs = super(AESCharField, self).deconstruct()
if self.prefix != "aes_str:::":
kwargs['prefix'] = self.prefix
return name, path, args, kwargs
def from_db_value(self, value, expression, connection, context):
"""
出库后解密数据
"""
if value is None:
return value
if value.startswith(self.prefix):
value = value[len(self.prefix):]
value = self.cipher.decrypt(value)
return value
def to_python(self, value):
"""
反序列化和Form clean()时调用,解密数据
"""
if value is None:
return value
elif value.startswith(self.prefix):
value = value[len(self.prefix):]
value = self.cipher.decrypt(value)
return value
def get_prep_value(self, value):
"""
入库前加密数据
"""
if isinstance(value, str) or isinstance(value, unicode):
value = self.cipher.encrypt(value)
value = self.prefix+value
elif value is not None:
raise TypeError(str(value)+" is not a valid value for AESCharField")
return value
WARNING:
使用说明
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。