MySQL 之Navicat Premium 12安装使用、pymysql模块使用、sql注入问题的产生与解决
閱讀目錄
-
一、Navicat Premium 12簡(jiǎn)介與使用:
-
二、pymysql模塊的使用:
查:
增刪改 -
三、sql注入問(wèn)題產(chǎn)生與解決方法:
本文內(nèi)容提要:
一、Navicat Premium 12簡(jiǎn)介與使用:
1、Navicat Premium 12是一套快速、可靠并價(jià)格相宜的數(shù)據(jù)庫(kù)管理工具,專為簡(jiǎn)化數(shù)據(jù)庫(kù)的管理及降低系統(tǒng)管理成本而設(shè)。它的設(shè)計(jì)符合數(shù)據(jù)庫(kù)管理員、開(kāi)發(fā)人員及中小企業(yè)的需要。Navicat 是以直覺(jué)化的圖形用戶界面而建的,讓你可以以安全并且簡(jiǎn)單的方式創(chuàng)建、組織、訪問(wèn)并共用信息。
其實(shí)Navicat Premium 12與MySQL直接的關(guān)系就相當(dāng)于pycharm與python解釋器之間的關(guān)系,而Navicat就是一種操作數(shù)據(jù)庫(kù)圖形化的一種功能加強(qiáng)軟件。學(xué)會(huì)它的目的只有一個(gè):更高效地讓我們操作管理查詢數(shù)據(jù)庫(kù)
2、Navicat Premium 12的使用:(由于Navicat Premium 12主要是圖形化操作界面,所以個(gè)人此處省去操作流程,具體流程都可以通過(guò)可視化的圖形界面自己去摸索清楚,這是作為程序員的最基本的要求吧。)
Navicat Premium 12安裝與破解方法詳見(jiàn):https://www.cnblogs.com/suguangti/p/10875870.html
對(duì)Navicat Premium 12的使用我們需要掌握大致以下幾種:
# Tip:批量加注釋:Ctrl+? 批量去注釋:Ctrl+shift+?
二、pymysql模塊的使用:
pymysql的一般使用方法:import pymysql # 導(dǎo)入pymysql模塊
查:
--------------------------------------------------------------------注:如果你對(duì)python感興趣,我這有個(gè)學(xué)習(xí)Python基地,里面有很多學(xué)習(xí)資料,感興趣的+Q群:895817687 -------------------------------------------------------------------# 與數(shù)據(jù)庫(kù)建立連接 conn = pymysql.connect(host='localhost',user='root',password='******',database='pymysql_ts',charset='utf8' )# 建立游標(biāo)連接 # cursor = conn.cursor() # 執(zhí)行完畢返回的結(jié)果,默認(rèn)用元組顯示 cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 以字典的方式顯示數(shù)據(jù)# pymysql 操作數(shù)據(jù)庫(kù)的方法: # 執(zhí)行sql語(yǔ)句 # ---------------------------------------------------------------------------------------------- 下面是pymysql_ts數(shù)據(jù)庫(kù)下的user_info表內(nèi)容: # id name password # 1 sgt 123456 # 2 jason 123456 # 3 smoke 123456 # ---------------------------------------------------------------------------------------------- # 1、驗(yàn)證登陸賬戶密碼: ''' while True:user = input('>>>>:').strip()pwd = input('>>>>:').strip()sql = "select * from user_info where name ='%s' and password ='%s'" % (user, pwd) # 這里的%s需要加引號(hào)# sql = 'select * from user_info' # 這里的%s需要加引號(hào)res = cursor.execute(sql) # 執(zhí)行sql語(yǔ)句,返回sql查詢成功的記錄if res:# sql查詢語(yǔ)句中的where條件能匹配到name和password字段,返回查詢記錄1,打印登陸成功后的信息print('登陸成功') # 獲取真實(shí)數(shù)據(jù)(該用戶名在數(shù)據(jù)庫(kù)中的記錄數(shù)據(jù))else:print('用戶名密碼錯(cuò)誤') # where條件匹配不到數(shù)據(jù),查詢數(shù)據(jù)為空,則賬號(hào)密碼錯(cuò)誤 ''' # ---------------------------------------------------------------------------------------------- sql = "select * from user_info" # sql語(yǔ)句,獲取user_info表的所有記錄 cursor.execute(sql) # 獲取真實(shí)數(shù)據(jù)之前一定要執(zhí)行sql語(yǔ)句 # ---------------------------------------------------------------------------------------------- # fetchall() 返回一個(gè)包含多個(gè)字典的列表 ''' print(cursor.fetchall()) # 獲取滿足where條件能查詢到的所有真實(shí)數(shù)據(jù) # 打印結(jié)果:[{'id': 1, 'name': 'sgt', 'password': '123456'},\ # {'id': 2, 'name': 'jason', 'password': '123456'}, {'id': 3, 'name': 'smoke', 'password': '123456'}] ''' # ---------------------------------------------------------------------------------------------- # fetchone() 返回一個(gè)字典 ''' print(cursor.fetchone()) # 打印結(jié)果:{'id': 1, 'name': 'sgt', 'password': '123456'} print(cursor.fetchone()) # 打印結(jié)果:{'id': 2, 'name': 'jason', 'password': '123456'} print(cursor.fetchone()) # 打印結(jié)果:{'id': 3, 'name': 'smoke', 'password': '123456'} ''' # 注意看結(jié)果,第一個(gè)id為1,后面依次是2、3,也就是說(shuō)第二次獲取結(jié)果是在第一次獲取結(jié)果之后開(kāi)始獲取的,這就和前面的cursor的 # 意思不謀而合,游標(biāo)連接,也就是每次獲取真實(shí)數(shù)據(jù)都是按游標(biāo)位置開(kāi)始獲取,類似于管道取值,取完一個(gè)少一個(gè)。 # 需求:如果我想每次獲取數(shù)據(jù)都從最一開(kāi)始獲取數(shù)據(jù),該如何實(shí)現(xiàn)? # 解決方法:相對(duì)移動(dòng),絕對(duì)移動(dòng) ''' # 相對(duì)移動(dòng): # cursor.scroll(1,'relative') # 數(shù)字1代表從當(dāng)前位置移動(dòng)一個(gè)記錄位置 # 比如: print(cursor.fetchone()) # 打印結(jié)果:{'id': 1, 'name': 'sgt', 'password': '123456'} cursor.scroll(1,'relative') # 第1個(gè)記錄位置已經(jīng)獲取完,從當(dāng)前記錄位置2開(kāi)頭向后移動(dòng)1個(gè)記錄位置,則下次打印就是從第3個(gè)記錄位置的開(kāi)頭開(kāi)始獲取 print(cursor.fetchone()) # 打印結(jié)果:{'id': 3, 'name': 'smoke', 'password': '123456'} ''' ''' # 絕對(duì)移動(dòng): # cursor.scroll(1,'absolute') # 從最開(kāi)頭的記錄位置開(kāi)始數(shù)的第1個(gè)位置后也就是第2個(gè)記錄位置開(kāi)頭開(kāi)始獲取數(shù)據(jù) print(cursor.fetchone()) # 打印結(jié)果:{'id': 1, 'name': 'sgt', 'password': '123456'} print(cursor.fetchone()) # 打印結(jié)果:{{'id': 2, 'name': 'jason', 'password': '123456'} print(cursor.fetchone()) # 打印結(jié)果:{'id': 3, 'name': 'smoke', 'password': '123456'} # 運(yùn)行到此處全部記錄全部取完 print(cursor.fetchone()) # 打印結(jié)果:None cursor.scroll(0, 'absolute') # 游標(biāo)移動(dòng)到在絕對(duì)位置(最開(kāi)始),0代表最開(kāi)始,如果是1代表0位置向后推一個(gè)記錄位置 print(cursor.fetchone()) # 打印結(jié)果:{'id': 1, 'name': 'sgt', 'password': '123456'} ''' # ---------------------------------------------------------------------------------------------- # fetchmany(n) 指定取n個(gè)記錄,返回一個(gè)n個(gè)字典數(shù)據(jù)的列表,不寫n默認(rèn)為1 # print(cursor.fetchmany()) # 獲取滿足where條件能查詢到的n條真實(shí)數(shù)據(jù),用一個(gè)包含n個(gè)字典的列表表示 # ''' print(cursor.fetchmany()) # 打印結(jié)果:[{'id': 1, 'name': 'sgt', 'password': '123456'}] # ''' cursor.close() # 關(guān)閉游標(biāo)連接 conn.close() # 斷開(kāi)數(shù)據(jù)庫(kù)連接增刪改
# ------------------------------------------------------------------------------------------------------------- # pymysql的增刪改: # 其實(shí)就是用sursor.execute(sql)去執(zhí)行sql語(yǔ)句,不同的就是sql語(yǔ)句是什么 # 先導(dǎo)入模塊: import pymysql # 建立數(shù)據(jù)庫(kù)連接: conn = pymysql.connect(host='localhost',user='root',password='******',database='pymysql_ts',charset='utf8' ) # 這里還列出該數(shù)據(jù)庫(kù)下的表user_info內(nèi)容: # id name password # 1 sgt 123456 # 2 jason 123456 # 3 smoke 123456 # 建立游標(biāo)連接(設(shè)置返回結(jié)果為字典模式) cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 開(kāi)始寫入sql數(shù)據(jù)操作語(yǔ)句: ''' user = input('輸入注冊(cè)用戶名:').strip() pwd = input('輸入注冊(cè)密碼:').strip() ''' # 還記得sql的注入導(dǎo)致的安全問(wèn)題嗎?這里不管是數(shù)據(jù)庫(kù)的增刪改查都要用上面的解決方法 # 方法為:sql語(yǔ)句字符串里面先寫上不帶引號(hào)的%s,傳入值在cursor.execute()中傳入。 # ----------------------------------------------------------------------------------- # 增(表中增加記錄用insert) ''' sql = "insert into user_info(name,password) values (%s,%s)" # 執(zhí)行sql語(yǔ)句: cursor.execute(sql, (user, pwd)) # 走到這里執(zhí)行execute實(shí)際是并沒(méi)有真正的修改數(shù)據(jù)庫(kù),接下來(lái)需要將修改行為和結(jié)果提交到數(shù)據(jù)庫(kù)才能修改生效: conn.commit() ''' # 此時(shí)打開(kāi)Navicat軟件,刷新下后,就能看到user_info表中新增了一條記錄 # 結(jié)果: # 輸入注冊(cè)用戶名:hello # 輸入注冊(cè)密碼:666888 # 1 sgt 123456 # 2 jason 123456 # 3 smoke 123456 # 4 hello 666888 # ----------------------------------------------------------------------------------- # 改(表中增加記錄用update) ''' sql = "update user_info set name=%s where id=4" cursor.execute(sql, 'world') conn.commit() ''' # 結(jié)果:(打開(kāi)Navicat軟件查看,需要刷新一下) # 1 sgt 123456 # 2 jason 123456 # 3 smoke 123456 # 4 world 666888 # ----------------------------------------------------------------------------------- # 一次新增多行記錄的方法:cursor.executemany(sql,[(),(),()]) sql = "insert into user_info(name,password) values (%s,%s)" # 插入多條,此處還是寫一個(gè)(%s,%s) cursor.executemany(sql, [('abc', '123'), ('def', '123'), ('ghi', '123')]) conn.commit() # 結(jié)果: # 1 sgt 123456 # 2 jason 123456 # 3 smoke 123456 # 4 world 666888 # 5 abc 123 # 6 def 123 # 7 ghi 123三、sql注入問(wèn)題產(chǎn)生與解決方法:
# ---------------------------------------------------------------------------------------------- # 接下來(lái)來(lái)個(gè)sql注入引發(fā)的安全問(wèn)題: # 通過(guò)上的驗(yàn)證用戶名密碼進(jìn)行登錄的過(guò)程,我們可以分析出,通過(guò)pymysql連接數(shù)據(jù)庫(kù)后后,實(shí)際上還是運(yùn)用sql語(yǔ)句來(lái)操作數(shù)據(jù)庫(kù), # 獲取數(shù)據(jù)庫(kù)中的記錄,比如通過(guò)where條件語(yǔ)句來(lái)拿用戶輸入的name和password與數(shù)據(jù)庫(kù)表中的對(duì)應(yīng)字段記錄進(jìn)行查詢,注意 # 這里是查詢,看能否查詢到用戶輸入的name和password的對(duì)應(yīng)字段記錄,如果有,就返回個(gè)記錄個(gè)數(shù),或者獲取到該記錄信息, # 如果查詢不到,就返回空,至此查詢完畢。 # 所以細(xì)心的人就會(huì)發(fā)現(xiàn)一個(gè)bug,或者安全問(wèn)題 # 我們仔細(xì)看看sql查詢語(yǔ)句:sql = "select * from user_info where name='%s' and password='%s'" % (user,pwd) # 這里如果在第一個(gè)%s做點(diǎn)手腳比如輸入:xxx' or 1=1 -- dfafdafafaf # 看不懂? 來(lái)分析下:我們知道在mysql里面--代表注釋,也就是--后面的都是注釋,無(wú)語(yǔ)句執(zhí)行效果。這樣就省去了密碼驗(yàn)證,同時(shí) # 前面xxx',這里有個(gè)單引號(hào),為何有個(gè)單引號(hào),我把第一個(gè)%s放進(jìn)sql語(yǔ)句中: # sql = "select * from user_info where name='xxx' or 1=1 -- dfafdafafaf' and password='%s'" % (user,pwd) # ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ # 看到?jīng)]有,這個(gè)select查詢語(yǔ)句變成什么樣了? select * from user_info where name='xxx' or 1=1 # 此時(shí)我們就看到上面語(yǔ)句結(jié)果,最后結(jié)果就是where條件1=1成立,表user_info中的全部數(shù)據(jù)都能被查詢到。 # ------------------------------------------------------------------------------------------------------------- # 來(lái)一段具體代碼: # 首先在數(shù)據(jù)庫(kù)pymysql_ts中有個(gè)表: # id name password # 1 sgt 123456 # 2 jason 123456 # 3 smoke 123456import pymysql # 建立數(shù)據(jù)庫(kù)連接: conn = pymysql.connect(host='localhost',user='root',password='******',database='pymysql_ts', # 找到其中一個(gè)數(shù)據(jù)庫(kù)charset='utf8' ) # 以返回結(jié)果為字典的形式建立游標(biāo)連接: cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 開(kāi)始操作數(shù)據(jù)庫(kù): user = input('輸入用戶名:').strip() pwd = input('輸入密碼:').strip() # 寫sql語(yǔ)句: ''' sql = "select * from user_info where name='%s' and password='%s'" % (user, pwd) # 執(zhí)行sql語(yǔ)句,返回查詢的記錄數(shù) cursor.execute(sql) # 打印獲取的查詢記錄: print(cursor.fetchall()) # 結(jié)果為: # 輸入用戶名:ddd' or 1=1 -- dfadfafafafa # 輸入密碼: # [{'id': 1, 'name': 'sgt', 'password': '123456'}, {'id': 2, 'name': 'jason', 'password': '123456'}, \ # {'id': 3, 'name': 'smoke', 'password': '123456'}] # 至此,這就是sql注入問(wèn)題,很顯然這是不安全的,也是不對(duì)的*_*,需要解決啊! ''' # ------------------------------------------------------------------------------------------------------------- # 解決方法:將用戶輸入的數(shù)據(jù)交給mysql去處理 # 在寫sql語(yǔ)句時(shí)候進(jìn)行變化一下: sql = "select * from user_info where name=%s and password=%s" cursor.execute(sql, (user, pwd)) # 去掉上面%s的引號(hào),將user和pwd傳入execute里面,pymysql會(huì)自動(dòng)識(shí)別%s自行傳入數(shù)據(jù) print(cursor.fetchall()) # 結(jié)果: # 輸入用戶名:xxx' or 1=1 -- dafafafafafa # 輸入密碼:fdaf # () # 最后總結(jié):為安全考慮,最好不要手動(dòng)去拼接查詢sql語(yǔ)句。 cursor.close() # 當(dāng)然最后養(yǎng)成好習(xí)慣關(guān)閉打開(kāi)的游標(biāo)連接 conn.close() # 同時(shí)斷開(kāi)的連接的數(shù)據(jù)庫(kù)總結(jié)
以上是生活随笔為你收集整理的MySQL 之Navicat Premium 12安装使用、pymysql模块使用、sql注入问题的产生与解决的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: MySQL数据库安装与Navicat P
- 下一篇: MySQL 之视图、 触发器、事务、存储