python连接数据库(pymysql)及数据库加密

内容:

1.pymysql介绍

2.pymysql基本使用

3.数据库加密

 

参考:http://www.cnblogs.com/wupeiqi/articles/5713330.html

 

 

 

1.pymysql介绍

pymsql是Python中操作MySQL的模块,其使用方法和MySQLdb几乎相同,在python3 中以及不支持MySQLdb这个模块了,所有我们现在只用学习pymysql即可

安装:

1 pip3 install pymysql

 

 

2.pymysql基本使用

(1)预备知识:SQL

sql详细:http://www.cnblogs.com/wyb666/p/9017402.html

1 数据库通过 SQL 来操作数据
2 SQL (结构化查询语言)-> 操作数据库的接口 也就是操作数据库的方法
3 增加数据  删除数据  修改数据  查询数据
4 CRUD
5 create retrieve update delete

 

(2)使用pymysql操作MySQL的大致流程

 1 import pymysql
 2   
 3 # 创建连接
 4 conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='t1')
 5 # 创建游标
 6 cursor = conn.cursor()
 7   
 8 # 执行SQL,并返回收影响行数
 9 effect_row = cursor.execute("update hosts set host = '1.1.1.2'")
10   
11 # 执行SQL,并返回受影响行数
12 #effect_row = cursor.execute("update hosts set host = '1.1.1.2' where nid > %s", (1,))
13   
14 # 执行SQL,并返回受影响行数
15 #effect_row = cursor.executemany("insert into hosts(host,color_id)values(%s,%s)", [("1.1.1.11",1),("1.1.1.11",2)])
16   
17   
18 # 提交,不然无法保存新建或者修改的数据
19 conn.commit()
20   
21 # 关闭游标
22 cursor.close()
23 # 关闭连接
24 conn.close()

 

(3)对以上过程的封装

看到这里你可能会好奇,以上那种用法不是蛮好吗,直接从上到下执行代码,干嘛还要封装,封装是为了代码的逻辑性更强,另外代码具有更多的可拓展性,我们自己封装直接封装成函数即可,不必封装成类(那样也可以不过太麻烦太复杂了),当然我们也可以使用别人的封装(后面要学到的SQLAlchemy就是一种简单的封装,其将对数据库的操作封装成对类的操作)

SQL操作无非可分为以下几种:

  • 创建库表
  • 增删改查数据

所以我将这些功能封装成相应的函数即可,如下所示:

  1 # __author__ = "wyb"
  2 # date: 2018/8/20
  3 import pymysql
  4 
  5 
  6 # 创建数据库中的表
  7 def create(conn):
  8     # 注意 CREATE TABLE 这种语句不分大小写
  9     sql_create = '''
 10     CREATE TABLE `users` (
 11         `id`    INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
 12         `username`    VARCHAR(200) NOT NULL UNIQUE,
 13         `password`    TEXT NOT NULL,
 14         `email`    TEXT
 15     )
 16     '''
 17     # 用 execute 执行一条 sql 语句
 18     conn.execute(sql_create)
 19     print('创建成功')
 20 
 21 
 22 # 向数据库中插入数据
 23 def insert(conn, username, password, email):
 24     sql_insert = '''
 25     INSERT INTO
 26         users(username,password,email)
 27     VALUES
 28         (%s, %s, %s);
 29     '''
 30     # 参数拼接要用 %s,execute 中的参数传递必须是一个 tuple 类型
 31     conn.execute(sql_insert, (username, password, email, ))
 32     print('插入数据成功')
 33 
 34 
 35 # 查询数据
 36 def select(conn):
 37     sql = '''
 38     SELECT
 39         *
 40     FROM
 41         users
 42     '''
 43     # 这是读取数据的套路
 44     conn.execute(sql)
 45     res = conn.fetchall()
 46     print("所有数据如下: ")
 47     for row in res:
 48         print(row)
 49 
 50 
 51 # 删除数据
 52 def delete(conn, user_id):
 53     sql_delete = '''
 54     DELETE FROM
 55         users
 56     WHERE
 57         id=%s
 58     '''
 59     # 注意, execute 的第二个参数是一个 tuple
 60     # tuple 只有一个元素的时候必须是这样的写法
 61     conn.execute(sql_delete, (user_id,))
 62     print("删除数据成功")
 63 
 64 
 65 # 更新数据
 66 def update(conn, user_id, email):
 67     sql_update = '''
 68     UPDATE
 69         `users`
 70     SET
 71         `email` = %s
 72     WHERE
 73         `id`= %s
 74     '''
 75     conn.execute(sql_update, (email, user_id))
 76     print("更新数据成功")
 77 
 78 
 79 # 主程序
 80 def main():
 81     # 指定数据库名字并打开 -> 没有会自动创建
 82     # 创建连接
 83     conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='root', db='wyb')
 84     print("打开数据库wyb")
 85     # 创建游标
 86     cursor = conn.cursor()
 87 
 88     # create 创建表结构 -> 注意创建表只能创建一次 创建已创建的表会报错
 89     # create(cursor)
 90 
 91     # insert 插入数据   -> 注意插入一次后下面的数据就不能再插入 因为用户名有限制(unique)
 92     # insert(cursor, 'wpz', '123', 'tggh@b.c')
 93 
 94     # delete 删除数据
 95     # delete(cursor, 1)
 96 
 97     # update 更新数据
 98     # update(cursor, 4, 'woz_wyb@qq.com')
 99     # select 查询数据
100     # select(cursor)
101 
102     # 最后提交: 必须用 commit 函数提交你的修改 否则你的修改不会被写入数据库
103     conn.commit()
104     # 用完数据库要关闭
105     cursor.close()
106     conn.close()
107 
108 
109 if __name__ == '__main__':
110     main()

先运行上述代码中的create函数,然后操作如下:

可以明显看到现在已经通过程序建立了数据库的表结构,接下来使用其他函数体验一下增删改查(insert、delete、update、select),每个函数运行完后在终端上

使用select * from users;查看表中数据变化

 

(4)fetch数据类型

默认获取的数据是元祖类型,如果想要或者字典类型的数据,即:

 1 import pymysql
 2   
 3 conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='t1')
 4   
 5 # 游标设置为字典类型
 6 cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
 7 r = cursor.execute("call p1()")
 8   
 9 result = cursor.fetchone()
10   
11 conn.commit()
12 cursor.close()
13 conn.close()

 

 

3.数据库加密

众所周知,数据库加密是十分重要的,因为数据库会存储一些敏感信息,比如密码,即使我们的程序没有任何的安全漏洞不会被黑客攻击,但是程序所在的服务器可能有安全漏洞,我们使用的数据库软件可能会有漏洞,因此要对数据中的一些敏感信息(比如密码)进行加密存储

(1)数据库加密方法

常见的加密算法有对称加密、非对称加密以及hash算法,一般数据库中敏感信息使用hash算法加密即可

常见的Hash算法:MD2、MD4、MD5、HAVAL、SHA、SHA-1、HMAC、HMAC-MD5、HMAC-SHA1

 

(2)加密实例

注册登录验证(密码加密):

 1 class User(Model):
 2     """
 3     User 是一个保存用户数据的 model
 4     现在只有两个属性 username 和 password
 5     """
 6     def __init__(self, form):
 7         self.id = form.get('id', None)
 8         self.username = form.get('username', '')
 9         self.password = form.get('password', '')
10 
11     # 加盐加密
12     @staticmethod
13     def salted_password(password, salt="`1234567890~!@#$%^&*()-=[];'\/,./ZXCVBNSADFYWQET"):
14         # salt:  "`1234567890~!@#$%^&*()-=[];'\/,./ZXCVBNSADFYWQET"
15         def md5hex(ascii_str):
16             return hashlib.md5(ascii_str.encode('ascii')).hexdigest()
17 
18         # 普通加密
19         hash1 = md5hex(password)
20         # 加盐加密
21         hash2 = md5hex(hash1 + salt)
22         return hash2
23 
24     # 注册
25     def validate_register(self):
26         pwd = self.password
27         self.password = self.salted_password(pwd)
28         # 用户名已存在就不允许注册 否则可以注册
29         if User.find_by(username=self.username) is None:
30             self.save()
31             return self
32         else:
33             return None
34 
35     # 登录
36     def validate_login(self):
37         u = User.find_by(username=self.username)
38         if u is not None:
39             return u.password == self.salted_password(self.password)
40         else:
41             return False
42 
43     # 修改密码
44     def change_pwd(self, form):
45         # 输入两次旧密码不一样
46         pwd1 = form.get("pwd1", "")
47         pwd2 = form.get("pwd2", "")
48         if pwd1 != pwd2:
49             res = {
50                 "msg": "两次输入的旧密码不一样",
51                 "data": None,
52             }
53             return res
54 
55         # 输入的旧密码正确就重置 否则就不重置
56         new_pwd = form.get("new_pwd", "")
57         if self.salted_password(pwd1) == self.password:
58             self.password = self.salted_password(new_pwd)
59             self.save()
60             res = {
61                 "msg": "重置密码成功",
62                 "data": self,
63             }
64         else:
65             res = {
66                 "msg": "输入的旧密码错误!",
67                 "data": None,
68             }
69         return res

注意:上述代码不是完整代码,但不用关心其他细节,只关心具体的加密以及验证方法

上述代码的加密逻辑:

使用python的hashlib加密模块,先用普通的md5的hash算法直接对密码进行加密,然后再对加密后的密文加上盐再进行加密

验证逻辑:

将用户输入的密码同样使用上述方法加密,如果最后结果和数据库中存的结果是一样的,那么就通过验证,否则验证失败

由此,可以得出结论:

假设密码存入数据库均经过上述过程中的hash加密,那么除了用户本人没有人会知道到底密码是什么(当然黑客破解也不是不行,但破解难度极大),所以当忘记密码时一般都不能直接找回密码,而是通过回答密保问题(或其他方式)来修改密码,因为除了用户自己没有人知道密码是什么

 

posted @ 2018-08-18 18:17  woz333333  阅读(10513)  评论(0编辑  收藏  举报