早前的一篇文章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字段加密的优雅实现的更多相关文章

  1. Django model字段类型清单

    转载:<Django model字段类型清单> Django 通过 models 实现数据库的创建.修改.删除等操作,本文为模型中一般常用的类型的清单,便于查询和使用: AutoField ...

  2. Django model 字段类型清单

    Django model字段类型清单 Django 通过 models 实现数据库的创建.修改.删除等操作,本文为模型中一般常用的类型的清单,便于查询和使用: AutoField 一个自动递增的整型字 ...

  3. Django model 字段类型及选项解析---转载

    model field 类型1.AutoField() 自增的IntegerField,通常不用自己设置,若没有设置主键,Django会自动添加它为主键字段,Django会自动给每张表添加一个自增的p ...

  4. Django——model字段类型 2

    Django 通过models实现数据库的创建.修改.删除等操作,Django中model作为数据资源指定了字段以及一些相应的功能,通常每个model对应数据库中的一张表,(每个model都是从dja ...

  5. Django model 字段类型及选项解析

    字段类型选择: AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bigint自增列,必须填入参数 ...

  6. Django model 字段详解

    字段类型选择: AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bigint自增列,必须填入参数 ...

  7. Django model字段类型(转)

    AutoField     一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段; 如果你不指定主键的话,系统会自动添加一个主键字段到你的 model.(参阅 _自 ...

  8. django进行model字段的自定义

    相信大家一定有web应用被攻击的经历,数据库安全是一个网站的必须课.django有很好的orm,但sql注入,或其他方式的攻击都是无法完全屏蔽的. 所以一般数据库都会对用户数据,如text类型的数据进 ...

  9. Django使用Signals监测model字段变化发送通知

    上一篇文章<运维效率之数据迁移自动化>中讲到了工单通知,本文将介绍工单通知实现过程中的一些小技巧.所有演示均基于Django2.0 阅读此篇文章你可以: 解锁一个python if的使用新 ...

随机推荐

  1. 华为分析X HUAWEI Ads,上线深度转化事件回传功能,让ROI 看得见!

    华为分析X HUAWEI Ads,上线深度转化事件回传功能,让ROI 看得见! 随着移动应用生态的流量成本攀升.行业竞争加剧,越来越多的广告商希望通过精准投放来获取更高质量的深度转化用户,比如二手车. ...

  2. 性能测试工具JMeter 基础(三)—— 创建测试计划

    如何创建一个完整的测试计划? 安装好JMeter后,通过根目录下的bin目录中的jmeter.bat启动JMeter 添加线程组(Thread Group) 在 Test Plan 鼠标右键 Add- ...

  3. fetch ios低版本兼容cannot clone a disturbed response

    报错信息 ios 11以下 cannot clone a disturbed response github.com/github/fetc- 问题发生场景 使用了一个或者多个三方库 三方库或者自己的 ...

  4. 单片机学习(十二)1-Wire通信协议和DS18B20温度传感器

    目录 一.DS18B20 1. DS18B20简介 2. 电路原理图 3. 内部结构 内部完整结构框图 存储器结构 二.单总线(1-Wire BUS) 1. 单总线简介 2. 电路规范 3. 单总线的 ...

  5. Gram-Schmidt图像融合

    遥感图像融合的定义是通过将多光谱低分辨率的图像和高分辨率的全色波段进行融合从而得到信息量更丰富的遥感图像.常用的遥感图像融合方法有Brovey\PCA\Gram-Schmidt方法.其中Gram-Sc ...

  6. Mysql常用sql语句(15)- cross join 交叉连接

    测试必备的Mysql常用sql语句 https://www.cnblogs.com/poloyy/category/1683347.html 前言 交叉连接就是求多表之间的笛卡尔积 讲道理..这个我都 ...

  7. Linux处理二进制文件工具

    处理目标文件的工具 在Linux系统中有大量可用的工具可以帮助我们理解和处理目标文件.特别地,GNU binutils包尤其有帮助,而且可以运行在每一个Linux平台上 序号 命令 说明 1 AR 创 ...

  8. C# Dapper基本三层架构使用 (四、WinForm UI层)

    UI层主要功能是显示数据和接受传输用户的数据,可以在为网站的系统运行提供交互式操作界面,表示层的应用方式比较常见,例如Windows窗体和Web页面. 在项目中增加WinForm应用程序,结构如下 添 ...

  9. aes加解密前后端-后台

    一.web.xml: <filter> <filter-name>fastLoginFilter</filter-name> <filter-class> ...

  10. weblogic漏洞分析之CVE-2017-3248 & CVE-2018-2628

    CVE-2017-3248 & CVE-2018-2628 后面的漏洞就是2017-3248的绕过而已,所以poc都一样,只是使用的payload不同 本机开启JRMP服务端 ->利用T ...