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