pymysql如何解決sql注入問(wèn)題深入講解
1. SQL 注入
SQL 注入是非常常見(jiàn)的一種網(wǎng)絡(luò)攻擊方式,主要是通過(guò)參數(shù)來(lái)讓 mysql 執(zhí)行 sql 語(yǔ)句時(shí)進(jìn)行預(yù)期之外的操作。
即:因?yàn)閭魅氲膮?shù)改變SQL的語(yǔ)義,變成了其他命令,從而操作了數(shù)據(jù)庫(kù)。
產(chǎn)生原因:SQL語(yǔ)句使用了動(dòng)態(tài)拼接的方式。
例如,下面這段代碼通過(guò)獲取用戶(hù)信息來(lái)校驗(yàn)用戶(hù)權(quán)限:
import pymysql sql = 'SELECT count(*) as count FROM user WHERE id = ' + str(input['id']) + ' AND password = "' + input['password'] + '"' cursor = dbclient.cursor(pymysql.cursors.DictCursor) cursor.execute(sql) count = cursor.fetchone() if count is not None and count['count'] > 0: print('登陸成功')
但是,如果傳入?yún)?shù)是:
input['id'] = '2 or 1=1'
你會(huì)發(fā)現(xiàn),用戶(hù)能夠直接登錄到系統(tǒng)中,因?yàn)樵?sql 語(yǔ)句的判斷條件被 or 短路成為了永遠(yuǎn)正確的語(yǔ)句。
這里僅僅是舉一個(gè)例子,事實(shí)上,sql 注入的方式還有很多種,這里不深入介紹了。
總之,只要是通過(guò)用戶(hù)輸入數(shù)據(jù)來(lái)拼接 sql 語(yǔ)句,就必須在第一時(shí)間考慮如何避免 SQL 注入問(wèn)題。
那么,如何防止 SQL 注入呢?
2. 預(yù)防 SQL 注入 – pymysql 參數(shù)化語(yǔ)句
pymysql 的 execute 支持參數(shù)化 sql,通過(guò)占位符 %s 配合參數(shù)就可以實(shí)現(xiàn) sql 注入問(wèn)題的避免。
import pymysql sql = 'SELECT count(*) as count FROM user WHERE id = %s AND password = %s' valus = [input['id'], input['password']] cursor = dbclient.cursor(pymysql.cursors.DictCursor) cursor.execute(sql, values) count = cursor.fetchone() if count is not None and count['count'] > 0: print('登陸成功')
這樣參數(shù)化的方式,讓 mysql 通過(guò)預(yù)處理的方式避免了 sql 注入的存在。
需要注意的是,不要因?yàn)閰?shù)是其他類(lèi)型而換掉 %s,pymysql 的占位符并不是 python 的通用占位符。
同時(shí),也不要因?yàn)閰?shù)是 string 就在 %s 兩邊加引號(hào),mysql 會(huì)自動(dòng)去處理。
3. 預(yù)防 SQL 注入 – mysql 存儲(chǔ)過(guò)程
數(shù)據(jù)庫(kù)存儲(chǔ)過(guò)程是 mysql 的一種高級(jí)用法,但是一般來(lái)說(shuō),并不建議使用數(shù)據(jù)庫(kù)的存儲(chǔ)過(guò)程。
主要原因是:
- 存儲(chǔ)過(guò)程的語(yǔ)法與普通 SQL 語(yǔ)句語(yǔ)法相差太大,增加維護(hù)成本
- 存儲(chǔ)過(guò)程在各數(shù)據(jù)庫(kù)間不通用且差別較大,給數(shù)據(jù)庫(kù)的移植和擴(kuò)展帶來(lái)困難
- 編寫(xiě)困難,數(shù)據(jù)庫(kù)腳本語(yǔ)言使用起來(lái)還是很不方便的,包括很多數(shù)據(jù)結(jié)構(gòu)的缺失,讓很多事情做起來(lái)很困難
- 調(diào)試?yán)щy,雖然有一些功能強(qiáng)大的 IDE 提供了數(shù)據(jù)庫(kù)存儲(chǔ)過(guò)程的調(diào)試功能,但是通常你需要同時(shí)在數(shù)據(jù)庫(kù)層面上和業(yè)務(wù)中同時(shí)進(jìn)行調(diào)試,兩處調(diào)試極為不便
- 業(yè)務(wù)耦合,編寫(xiě)存儲(chǔ)過(guò)程通常是需要在其中放入部分業(yè)務(wù)邏輯,這使得業(yè)務(wù)分散在數(shù)據(jù)層,業(yè)務(wù)層與數(shù)據(jù)層的耦合對(duì)于項(xiàng)目維護(hù)和擴(kuò)展都會(huì)帶來(lái)極大地不便。
但是,雖然不建議使用存儲(chǔ)過(guò)程,但是畢竟可以依賴(lài)他實(shí)現(xiàn)各種跨語(yǔ)言的 sql 注入預(yù)防,在復(fù)雜的場(chǎng)景下還是有其使用價(jià)值的。(以后需要用再去詳細(xì)學(xué),這里只作簡(jiǎn)單介紹)
3.1. 存儲(chǔ)過(guò)程編寫(xiě)
delimiter \DROP PROCEDURE IF EXISTS proc_sql \CREATE PROCEDURE proc_sql ( in nid1 INT, in nid2 INT, in callsql VARCHAR(255) ) BEGIN set @nid1 = nid1; set @nid2 = nid2; set @callsql = callsql; PREPARE myprod FROM @callsql; -- PREPARE prod FROM 'select * from tb2 where nid>? and nid<?'; 傳入的值為字符串,?為占位符 -- 用@p1,和@p2填充占位符 EXECUTE myprod USING @nid1,@nid2; DEALLOCATE prepare myprod; END\delimiter ;
3.2. pymsql 中調(diào)用
import pymysql cursor = conn.cursor() mysql="SELECT * FROM user where nid > ? and nid < ?" cursor.callproc('proc_sql', args=(11, 15, mysql)) rows = cursor.fetchall() conn.commit()
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
TDSQL 安裝部署附圖的實(shí)現(xiàn)(圖文)
這篇文章主要介紹了TDSQL 安裝部署附圖的實(shí)現(xiàn)(圖文),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10大數(shù)據(jù)之Spark基礎(chǔ)環(huán)境
本篇文章開(kāi)始介紹Spark基礎(chǔ)知識(shí),包括Spark誕生的背景,應(yīng)用環(huán)境以及入門(mén)案例等,感興趣的同學(xué)可以參考閱讀本文2023-04-04新推出的金融版eXtremeDB 6.0功能改進(jìn)預(yù)覽
這篇文章主要介紹了新推出的金融版eXtremeDB 6.0功能改進(jìn)預(yù)覽,如運(yùn)用SQL, Python實(shí)現(xiàn)的基于矢量的統(tǒng)計(jì)功能、分布式的查詢(xún)處理、市場(chǎng)數(shù)據(jù)壓縮等內(nèi)容,需要的朋友可以參考下2014-10-10數(shù)據(jù)分析數(shù)據(jù)庫(kù)ClickHouse在大數(shù)據(jù)領(lǐng)域應(yīng)用實(shí)踐
這篇文章主要為大家介紹了數(shù)據(jù)分析數(shù)據(jù)庫(kù)ClickHouse在大數(shù)據(jù)領(lǐng)域應(yīng)用實(shí)踐,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04使用sqlalchemy-gbasedbt連接GBase 8s數(shù)據(jù)庫(kù)的步驟詳解
這篇文章主要介紹了使用sqlalchemy-gbasedbt連接GBase 8s數(shù)據(jù)庫(kù)的步驟詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04