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的使用新 ...
随机推荐
- 洛谷P1083 借教室 题解
题目 [NOIP2012 提高组] 借教室 题解 这道题是几周之前做到的一道题,本来不想讲的,因为这道题也是用到了二分答案的方法,这类题目之前已经发布过两篇题解了.但这道题还运用了差分数组这个思想,所 ...
- K8S——Pod
一.Pod概念 二.Pod存在的意义 三.Pod的实现机制 四.Pod镜像拉取策略 五.Pod资源限制 六.Pod重启机制 七.Pod的健康检查 八.Pod调度策略(创建Pod流程)
- Jetpack Compose学习(4)——Image(图片)使用及Coil图片异步加载库使用
原文地址 Jetpack Compose学习(4)--Image(图片)使用及Coil图片异步加载库使用 | Stars-One的杂货小窝 本篇讲解下关于Image的使用及使用Coil开源库异步加载网 ...
- Object.keys( )与 for in 区别
for in 一般用于对象的遍历: let obj = { a:1, b:2, } for(let key in obj){ console.log(key) } // a // b Object.k ...
- python动态网站爬虫实战(requests+xpath+demjson+redis)
目录 前言 一.主要思路 1.观察网站 2.编写爬虫代码 二.爬虫实战 1.登陆获取cookie 2.请求资源列表页面,定位获得左侧目录每一章的跳转url(难点) 3.请求每个跳转url,定位右侧下载 ...
- PHP中的MySQLi扩展学习(五)MySQLI_STMT对象操作
就像 PDO 中的 PDO_Statment 对象一样,MySQLI_STMT 对象也是一个预处理语句所形成的对象,专门用来操作 MySQLi 所生成的预处理语句的.其实操作方式之类也都比较相似,不外 ...
- PHP没有定时器?
确实,PHP没有类似于JS中的setInterval或者setTimeout这样的原生定时器相关的函数.但是我们可以通过其他方式来实现,比如使用declare. 先来看看是如何实现的,然后我们再好好学 ...
- PHP的变量赋值
这个标题估计很多人会不屑一顾,变量赋值?excuse me?我们学开发的第一课就会了好不好.但是,就是这样基础的东西,反而会让很多人蒙圈,比如,值和引用的关系.今天,我们就来具体讲讲. 首先,定义变量 ...
- PHP中的垃圾回收相关函数
之前我们已经学习过 PHP 中的引用计数以及垃圾回收机制的概念.这些内容非常偏理论,也是非常常见的面试内容.而今天介绍的则是具体的关于垃圾回收的一些功能函数.关于之前的两篇介绍文章,大家可以到文章底部 ...
- 微信公众号jssdk分享接口onMenuShareAppMessage自定义的参数无效,微信分享失败原因
使用jssdk为jweixin-1.4.0.js updateTimelineShareData,安全域名接口也设置正确,可就是分享,转发朋友圈不成功. 解决方案:采用<script src=& ...