python鏈接數據庫(pymysql)及數據庫加密

內容:html

1.pymysql介紹python

2.pymysql基本使用mysql

3.數據庫加密算法

 

參考:http://www.cnblogs.com/wupeiqi/articles/5713330.htmlsql

 

 

 

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算法:MD二、MD四、MD五、HAVAL、SHA、SHA-一、HMAC、HMAC-MD五、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加密,那麼除了用戶本人沒有人會知道到底密碼是什麼(固然黑客破解也不是不行,但破解難度極大),因此當忘記密碼時通常都不能直接找回密碼,而是經過回答密保問題(或其餘方式)來修改密碼,由於除了用戶本身沒有人知道密碼是什麼

相關文章
相關標籤/搜索