Django Model字段加密的优雅实现
早前的一篇文章Django开发密码管理表实例有写我们写了个密码管理工具来实现对密码的管理,当时加密解密的功能在view层实现,一直运行稳定所以也没有过多关注实现是否优雅的问题。最近要多加几个密码表再次回头看之前的代码发现加解密在view层实现较为繁琐,尤其是使用了Sadmin公共库之后view的代码简洁了很多,若再在view层处理显然不够优雅,是时候用更优雅的方式来实现了
Sadmin增删改查
对数据库表的增删改查是开发过程中最常用到的功能,之前的文章也介绍过我们通过封装Sadmin公共库用最为简洁的代码实现了对表的增删改查操作,具体有多简洁,看下边的代码
class TableList(ListCreateView):
model = Table
template = 'password/table.html'
permission = {'get': 'password.select_table', 'post': 'password.create_table'}
class TableDetail(RetrieveUpdateDestroyView):
model = Table
permission = {'get': 'password.select_table', 'put': 'password.update_table',
'delete': 'password.delete_table'}
TableList
类可以实现对表的查询以及新建表数据,TableDetail
可以实现对表内单条数据的查询、修改和删除,对应了两条URL
path('table/', views.TableList.as_view(), name='table-list-url'),
path('table/<int:pk>/', views.TableDetail.as_view(), name='table-detail-url'),
如果在view层实现表字段的加密的话,那就要重写TableList
的post方法,以及TableDetail
类的put方法,非常麻烦,那有什么更为优雅的方法呢?对表字段的处理最好能在表发生变化的时候来处理,直接在model层来实现显然要比view更合适,model层来实现的话通过Django的signals或是重写model的save方法都是不错的选择
至于究竟是用signals还是重写save方法,两者都可以实现,个人觉得对于简单的处理逻辑采用重写save的方式比较好,而对于复杂的处理逻辑采用signals更清晰,而对于我们这个对字段进行加密的需求,逻辑简单代码也不需要太多,直接采用重写save的方式就好了
重写model的save方法
对于加密解密的核心代码可以参考文章Django开发密码管理表实例给出的源码,重写model的save方法代码如下
class Table(models.Model):
username = models.CharField(max_length=64, verbose_name='用户名')
password = models.CharField(max_length=512, verbose_name='密码')
def __str__(self):
return self.application_name
def save(self, *args, **kwargs):
_encrypt = True
if self.pk:
old_password = Table.objects.get(id=self.id)
_encrypt = False if old_password.password == self.password else True
if _encrypt:
_m = RsaCrypto().encrypt(self.password)
if _m.get('state'):
self.password = _m.get('message')
else:
raise Exception('加密失败:' + _m.get('message'))
super(Table, self).save(*args, **kwargs)
对于密码加密,通常会在首次新加记录,以及更新记录密码发生变化的情况下进行
每当save时如何判断是insert还是update呢?可以通过是否存在self.pk
来判断,Django的model必须有一个字段为主键,如果用户没有设置主键字段,那么Django会默认创建一个名为id
的字段作主键,主键也用pk
别名来表示,所以可以通过self.pk
是否存在来判断本次save究竟是insert还是update
当本次save为update时,我们也需要判断密码字段是否发生了变化,如果没有变化则不需要调用加密方法,判断字段是否变化就需要获取字段提交前的值,提交前的值可以通过Table.objects.get(id=self.id)
来获取
有了以上这些信息,那加密就水到渠成了。我们优雅的实现了字段的加密,那对于解密呢?个人觉得同样放在model里比写在veiw里更合适,可以在mdel里加个decode_password
的方法
class Table(models.Model):
...
def decode_password(self):
_m = RsaCrypto().decrypt(self.password)
if _m.get('state'):
return {
'state': 1,
'message': _m.get('message'),
'username': self.username
}
else:
return {'state': 0, 'message': 'Error: ' + _m.get('message')}
需要解密时调用Model的decode_password
方法就可以了
def decode_password(request, pk):
try:
_t = Table.objects.get(id=pk)
return JsonResponse(_t.decode_password())
except Exception as e:
return JsonResponse({'state': 0, 'message': 'Error: ' + str(e)})
写在最后
个人对代码有一点洁癖,实现功能也以简单实用为主,能2行搞定的绝对不会写3行,能有更优的解法就会毫不犹豫去重构,同时也坚决反对“又不是不能用”的说法。对于以上实现是否优雅,或是有更好的解决方法,欢迎讨论
Django Model字段加密的优雅实现的更多相关文章
- Django model字段类型清单
转载:<Django model字段类型清单> Django 通过 models 实现数据库的创建.修改.删除等操作,本文为模型中一般常用的类型的清单,便于查询和使用: AutoField ...
- Django model 字段类型清单
Django model字段类型清单 Django 通过 models 实现数据库的创建.修改.删除等操作,本文为模型中一般常用的类型的清单,便于查询和使用: AutoField 一个自动递增的整型字 ...
- Django model 字段类型及选项解析---转载
model field 类型1.AutoField() 自增的IntegerField,通常不用自己设置,若没有设置主键,Django会自动添加它为主键字段,Django会自动给每张表添加一个自增的p ...
- Django——model字段类型 2
Django 通过models实现数据库的创建.修改.删除等操作,Django中model作为数据资源指定了字段以及一些相应的功能,通常每个model对应数据库中的一张表,(每个model都是从dja ...
- Django model 字段类型及选项解析
字段类型选择: AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bigint自增列,必须填入参数 ...
- Django model 字段详解
字段类型选择: AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bigint自增列,必须填入参数 ...
- Django model字段类型(转)
AutoField 一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段; 如果你不指定主键的话,系统会自动添加一个主键字段到你的 model.(参阅 _自 ...
- django进行model字段的自定义
相信大家一定有web应用被攻击的经历,数据库安全是一个网站的必须课.django有很好的orm,但sql注入,或其他方式的攻击都是无法完全屏蔽的. 所以一般数据库都会对用户数据,如text类型的数据进 ...
- Django使用Signals监测model字段变化发送通知
上一篇文章<运维效率之数据迁移自动化>中讲到了工单通知,本文将介绍工单通知实现过程中的一些小技巧.所有演示均基于Django2.0 阅读此篇文章你可以: 解锁一个python if的使用新 ...
随机推荐
- 移动端ios上下滑动翻页事件失效
移动端开发过程中,在添加上下滑动事件时候,引入了最常用的移动端库zepto.js及其touch模块,有一种现象,安卓的手机没有问题,上下滑动翻页很正常 :但是到了ios上面,好啊,上下滑动会出现弹性滚 ...
- Mysql常用基础命令操作
常见操作命令:1.连接Mysql (客户端工具NaviCat.phpMyAdmin.MySQL-Front)格式: mysql -h 主机地址 -u用户名 -p用户密码(1)连接到本机上的MYSQL. ...
- Filter案例之敏感词过滤和代理模式
一.需求分析 二 .代理模式 1.概念 2.代码实现 代理对象可以强转为真实对象,即对应的接口类: 3.通过代理增强方法 其中,方法对象invoke真实对象,反射原理: 三.过滤敏感词汇案例代码实现 ...
- view+element+java登陆验证码
一.前端: 1.页面标签: <el-row :gutter="20"> <el-col :span="24"> <el-input ...
- React Native踩坑日记 —— tailwind-rn
项目背景 在项目的初始阶段,我们需要建立自己的design system,我们spike了一些方案,tailwind-rn就是其中一种,如果有用到或者即将用到tailwind-rn的,可以进来看一看, ...
- ByteArrayOutputStream小测试
import java.io.*; import org.junit.Test; public class ByteArrayOutputStreamTest { @Test public void ...
- excel中快速删除空白行/区域
选中要删除的空白所在的列 按Ctrl+G 选择空值 右键->删除->整行
- kubectl apply部署时可以用 --record 方便记录版本 和回退
1.部署时正常时下面的 kubectl apply -f http.yaml 2.如果修改文件文件重新部署或者之前有上一个版本的 想回退上一个的 可以无感知的回退回去 不影响业务 其中http-de ...
- [Apache Atlas] Atlas 架构设计及源代码简单分析
Apache Atlas 架构图 Atlas 支持多数据源接入:Hive.HBase.Storm等 Type System Type Atlas 中定义了一些元数据类型 ── AtlasBaseTyp ...
- 获取发布版SHA1和调试版SHA1
总结 调试版: 常见问题 | 高德地图API (amap.com) 发布版: 首先需要生成签名 Android Studio生成签名文件,自动签名,以及获取SHA1和MD5值_donkor_的博客-C ...