需求: 

  不知道大家有没有遇到过这样的需求:自己的服务器出于对数据库安全的保护,需要对存储的数据进行加密保护。这样万一数据库被人拿到,别人也不能拿到数据库里面的内容。这里还有一个前提:前端的展示页面是不对外公开的,需要验证才能进入。为什么提这个,就是因为前端所展现的内容一定是明文的,不然管理人员如何阅读查看呢(这也给爬虫留下了机会,不过关键还是在于你能够拿到管理人员的密码)。

 

背景介绍:

  •   系统数据库采用的是Mongodb;
  •   后台使用的语言是Python;
  •   python与数据库的交互主要借助于Pymongo。

 

寻找突破口:

  从这里面我们大概可以发现有两个地方可以下手:

  1. 每次进行数据库操作的时候对数据进行加解密操作。具体来说就是:增删改查之前对数据进行加密(这样才能在数据库中找到),查找之后对数据进行解密(这样才能得到明文的内容进行展示);
  2. 修改与数据库进行交互的库Pymongo,让其实现加密存储,解密读取。

  比较下两种方法的优缺点:

  第一种方案:实现很简单,但不适合大项目。项目一旦大了,对数据库的操作不太可能完全通过某个数据库操作模块来实现,这样修改起来就很麻烦了;

  第二种方案:对业务逻辑是透明的。并不需要对网站代码进行修改,但需要对pymongo的源码进行分析,找出增删改查相应的关键点,在这些关键点上进行加解密操作。

  由于自己的项目确实不小,存在很多模块。所以选择了第二种方案。

 

具体步骤:

  1. 实现加解密函数库

    既然需要用到加解密操作,那么显然需要实现自己的加解密函数。具体实现中我使用了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
View Code

  2. 找到pymongo中进行增删改查操作的代码并插入加解密的操作

    经过研读pymongo的代码发现,增删改查的操作主要是在两个文件里面进行的:collection.py,cursor.py。所以在实现过程中,我只对这两个文件的相关部分进行了修改(注意,我使用pymongo版本是2.7,如果使用其他版本的可能会有差别)。

    我就简单列举一下我修改的函数吧,大家有兴趣可以上github具体查看下整个实现:

    •  collection.py:
      • insert
      • update
      • find_one
      • remove
      • aggregate
    •  cursor.py
      • __getitem__
      • __send_message

    有兴趣的可以看看代码,github地址:https://github.com/ybAmazing/encrypt_pymongo

 

思考和总结

  这个功能的必要性,我自己是持怀疑态度的。由于对黑客技术也不是很了解,也说不出个所以然来。大家如果有什么想法或建议的,可以留言,相互交流学习一下。

 

 

posted @ 2016-09-12 13:47 Amazing_Y 阅读(6298) 评论(3) 推荐(0) 编辑
摘要: 1.远程拷贝数据库 2.数据库备份/恢复(导出/导入) mongoexport, mongoimport, mongodump, mongorestore 3.查询指定列数据: 4.建立索引 5.删除db 阅读全文
posted @ 2016-08-10 16:45 Amazing_Y 阅读(133) 评论(0) 推荐(0) 编辑
摘要: 基于SSH的连接 上传文件: pscp -P 28661(portNum) -pw password sourceFilePath user@serverIP:destinationFilePath 下载文件: pscp -P 28661(portNum) -pw password user@ser 阅读全文
posted @ 2016-07-20 13:47 Amazing_Y 阅读(749) 评论(0) 推荐(0) 编辑
摘要: 背景介绍 我们学校的教务系统的是以学生学号作为登陆账号,初始密码是自己的生日。一点点想法 每次期末查成绩的时候,我都会有一个想法,要是我能跑到系统后台,把自己的成绩修改一下,那该时间多么舒坦的事情啊。当然,我目前还并没有这么做。^_^ 光看自己的成绩不过瘾,有时候还想看下同学的成绩。怎么办呢?突... 阅读全文
posted @ 2015-01-25 23:46 Amazing_Y 阅读(14404) 评论(42) 推荐(13) 编辑
摘要: css属性编写顺序:影响文档流的属性(比如:display, position, float, clear, visibility, table-layout等)自身盒模型的属性(比如:width, height, margin, padding, border等)排版相关属性(比如:font, line-height, text-align, text-indent, vertical-align等等)装饰性属性(比如:color, background, opacity, cursor等)生成内容的属性(比如:content, list-style, quotes等)mysql基本操作(例 阅读全文
posted @ 2013-08-28 12:00 Amazing_Y 阅读(637) 评论(0) 推荐(0) 编辑
摘要: 这个是STL中的特殊容器,和学习其他容器vector,queue,stack一样,我们用类比的方式来学习它。首先,当然是怎么定义了。。priority_queue<Type, Container, Functional>既然是优先队列,总该有个优先的原则吧,怎么去优先呢?显然你要给个标准它。这里我们就需要提供一个比较函数,记住STL中是使用"<"来进行优先级比较的。首先我们利用默认的比较函数来定义队列:priority_queue<int> q;这样我们声明的a是用基本容器vector装的int型数据,队列头是数值大的元素。要是我们想构造一个小 阅读全文
posted @ 2013-05-12 22:58 Amazing_Y 阅读(218) 评论(0) 推荐(0) 编辑
摘要: 早就想写写几个排序的算法了,原来一直是直接调用库函数sort()和qsort(),导致自己对它们内部是实现机理有些忽视。现在就把我刚刚手写的一个归并排序(时间复杂度是o(n*log(n))),其中我是用递归来实现的。在代码中我还比较了手写归并,sort(),qsort(),的效率。 先对程序中所用的数据结构做下声明,方便大家理解接下来的程序:int res[cnt];int num1[cnt],num2[cnt],num3[cnt]; 其中res是归并时用的辅助数组,num1,num2,num3都是保存的是待排序的数,为了使程序具有可比性,所以把它们的元素赋成相同的值:void ini... 阅读全文
posted @ 2013-01-04 21:07 Amazing_Y 阅读(2892) 评论(3) 推荐(1) 编辑
摘要: 矩阵的快速幂是用来高效地计算矩阵的高次方的。将朴素的o(n)的时间复杂度,降到log(n)。这里先对原理(主要运用了矩阵乘法的结合律)做下简单形象的介绍:一般一个矩阵的n次方,我们会通过连乘n-1次来得到它的n次幂。但做下简单的改进就能减少连乘的次数,方法如下:把n个矩阵进行两两分组,比如:A*A*A*A*A*A => (A*A)*(A*A)*(A*A)这样变的好处是,你只需要计算一次A*A,然后将结果(A*A)连乘自己两次就能得到A^6,即(A*A)^3=A^6。算一下发现这次一共乘了3次,少于原来的5次。其实大家还可以取A^3作为一个基本单位。原理都一样:利用矩阵乘法的结合律,来减少 阅读全文
posted @ 2012-11-29 21:29 Amazing_Y 阅读(37768) 评论(4) 推荐(20) 编辑
摘要: 显然这是两个用的对数据经行比较的方法。但两者是有区别的,熟悉C/C++的朋友们一定有对地址和值这两个概念经行比较深入的研究。但是C#为了安全起见,把地址(也就是指针)这个东西给取消了,取而代之的是对象的引用(其实这个也是在栈上的和地址所处的地方是一样的)。好了,现在我们来看==和equals的区别。1.从最简单的值类型入手1 int a = 1;2 int b = 1;3 Console.WriteLine(a.Equals(b));4 Console.WriteLine((a == b).ToString());结果是:True True这是很显然的,因为==... 阅读全文
posted @ 2012-10-13 15:30 Amazing_Y 阅读(2795) 评论(8) 推荐(2) 编辑
摘要: 题目链接题目大意:给你两个字符串,让你求第二个字符串在第一个字符串中出现了几次,注意不能有重叠的区间。由于这题的数据不大,所以朴素的字符串匹配就能解决问题。代码如下: 1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 char str[1005],substr[1005]; 6 int len1,len2,cnt; 7 char *p,*q; 8 9 int main()10 {11 do12 {13 cnt=0;14 scanf("%s",str.. 阅读全文
posted @ 2012-09-22 00:36 Amazing_Y 阅读(479) 评论(0) 推荐(0) 编辑
点击右上角即可分享
微信分享提示