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加密,那么除了用戶本人沒有人會知道到底密碼是什么(當然黑客破解也不是不行,但破解難度極大),所以當忘記密碼時一般都不能直接找回密碼,而是通過回答密保問題(或其他方式)來修改密碼,因為除了用戶自己沒有人知道密碼是什么

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM