需求: 前端
不知道你们有没有遇到过这样的需求:本身的服务器出于对数据库安全的保护,须要对存储的数据进行加密保护。这样万一数据库被人拿到,别人也不能拿到数据库里面的内容。这里还有一个前提:前端的展现页面是不对外公开的,须要验证才能进入。为何提这个,就是由于前端所展示的内容必定是明文的,否则管理人员如何阅读查看呢(这也给爬虫留下了机会,不过关键仍是在于你可以拿到管理人员的密码)。python
背景介绍:git
寻找突破口:github
从这里面咱们大概能够发现有两个地方能够下手:算法
比较下两种方法的优缺点:数据库
第一种方案:实现很简单,但不适合大项目。项目一旦大了,对数据库的操做不太可能彻底经过某个数据库操做模块来实现,这样修改起来就很麻烦了;安全
第二种方案:对业务逻辑是透明的。并不须要对网站代码进行修改,但须要对pymongo的源码进行分析,找出增删改查相应的关键点,在这些关键点上进行加解密操做。服务器
因为本身的项目确实不小,存在不少模块。因此选择了第二种方案。ide
具体步骤:函数
既然须要用到加解密操做,那么显然须要实现本身的加解密函数。具体实现中我使用了pycrypto加密库,利用其中的AES加密算法对文档进行加解密。加解密过程不难,利用里递归实现,代码实现以下:
1 from Crypto.Cipher import AES 2 import bson 3 from bson.binary import Binary, UUIDLegacy 4 from pymongo import config 5
6 key = config.key 7
8 obj = AES.new(key) 9
10 def encrypt_helper(s): 11 length = 16 - (len(s) % 16) 12 s += chr(length) * length 13 s = obj.encrypt(s) 14 s = Binary(s, 1) 15 return s 16
17 def decrypt_helper(s): 18 s = obj.decrypt(s) 19 buf = bytearray(s) 20 length = buf[-1] 21 s = s[: -length] 22 return s 23
24 def encrypt_doc(doc): 25 if isinstance(doc, str): 26 return encrypt_helper(doc) 27 if isinstance(doc, dict): 28 for key in doc: 29 if cmp(key, "channel") != 0: 30 doc[key] = encrypt_doc(doc[key]) 31 return doc 32
33 if isinstance(doc, list): 34 for i in range(len(doc)): 35 doc[i] = encrypt_doc(doc[i]) 36 return doc 37 return doc 38
39
40 def decrypt_doc(doc): 41 if isinstance(doc, Binary): 42 return decrypt_helper(doc) 43 if isinstance(doc, dict): 44 temp_doc = {} 45 for key in doc: 46 #version 1
47 #doc[key] = decrypt_doc(doc[key])
48
49 #version 2
50 temp_doc[str(key)] = decrypt_doc(doc[key]) 51 doc = temp_doc 52 return doc 53
54 if isinstance(doc, list): 55 for i in range(len(doc)): 56 doc[i] = decrypt_doc(doc[i]) 57 return doc 58 return doc
2. 找到pymongo中进行增删改查操做的代码并插入加解密的操做
通过研读pymongo的代码发现,增删改查的操做主要是在两个文件里面进行的:collection.py,cursor.py。因此在实现过程当中,我只对这两个文件的相关部分进行了修改(注意,我使用pymongo版本是2.7,若是使用其余版本的可能会有差异)。
我就简单列举一下我修改的函数吧,你们有兴趣能够上github具体查看下整个实现:
有兴趣的能够看看代码,github地址:https://github.com/ybAmazing/encrypt_pymongo
思考和总结
这个功能的必要性,我本身是持怀疑态度的。因为对黑客技术也不是很了解,也说不出个因此然来。你们若是有什么想法或建议的,能够留言,相互交流学习一下。