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的使用新 ...
随机推荐
- PPP协议、PPPoE协议、L2TP协议的关系
1. 简述 首先对这3中协议做一个简单的描述: 协议 协议类型 描述 PPP 点对点链路层协议 应用最广泛的点对点协议,可应用在多种网络,改善了SLIP协议的不足 PPPoE 点对点链路层协议 对PP ...
- Java链表练习题小结
链表 链表(Linked List)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer).一个链表节点至少包含一个 数据域和 ...
- freeswitch python模块
概述 freeswitch支持多种语言的业务开发,包括C/C++,java,python,js,lua,Golang等等.freeswitch在使用python做业务开发时,有俩种接入方式,一种是ES ...
- 第十一章 Net 5.0 快速开发框架 YC.Boilerplate --图数据库模块Neo4j
在线文档:http://doc.yc-l.com/#/README 在线演示地址:http://yc.yc-l.com/#/login 源码github:https://github.com/linb ...
- C# lambda 实现 Ascii 排序
var dir = new Dictionary<string, string>(); dir.Add("channelId", "1& ...
- 网页兼容最新IE声明meta方法
第三种,总是使用最新版本文档模式. 以下是例子: <meta http-equiv="X-UA-Compatible" content="IE=edge" ...
- Docker系列(8)- 常用其他命令(1) | 日志、元数据、进程的查看
后台启动容器 # 命令 docker run -d 镜像名 [root@localhost ~]# docker run -d centos #问题:docker ps,发现centos停止了 #常见 ...
- win10系统git的安装与使用命令
一.git简介 git是一个开源的分布式版本控制系统,可以高效的进行项目版本管理.分布式相比集中式最大的区别在于:分布式开发者可以提交到本地,每个开发者通过克隆在本地机器上拷贝一个完整的git仓库. ...
- animate.css VUE 使用
1.安装 npm i animate.css --save 2.引用 main.jsimport 'animate.css' 3.使用 <img v-show="welcomeinde ...
- LR进行内外网附件上传并发——实践心得
刚开始接触LR的时候,做了一次内外网附件上传的并发测试,比较简单,但当时理解有些欠缺.以下为当时的实践心得: 1.分内外网测试的意义: 内网测试主要看负载压力情况等,外网测试主要考虑网络带宽.网络延时 ...