成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一次SQL請求,返回分頁數據和總條數,你學會了嗎?

數據庫 其他數據庫
本文通過我們最初開始數據庫編程時的一個實踐, 提出在【一次sql請求中執行多次sql查詢】的猜想;了解到client_multi_statements= false 確實能避免一部分sql注入風險;之后落地到sql注入的原理, 給出了參數化查詢(預編譯語句)能防止sql注入的核心機制。

日常搬磚,總少不了需要獲取分頁數據和總行數。

一直以來的實踐是編碼兩次sql請求,分別拉分頁數據和totalCount。

最近我在思考:

常規實踐為什么不是 在一次sql請求中中執行多次sql查詢或多次更新,顯而易見的優勢:

① 能顯著減低“客戶端和服務器之間的網絡往返次數”,提高吞吐量② 簡化客戶端代碼邏輯

1. mysql 默認單sql請求單語句

mysql客戶端選項client_multi_statements默認為false:會禁止多條 SQL 語句的執行,這意味著在單個sql請求中只有第一條 SQL 語句會被執行,后續的 SQL 語句將被忽略。

這是一種提高數據庫操作安全性的方法,可以有效防止 SQL 注入攻擊和意外執行多條語句帶來的風險。

MySQL客戶端支持修改這樣的設定 :client_multi_statements=true。

圖片圖片

劣勢:存在sql注入的風險, 錯誤處理比較復雜。

(1) go-sql-driver開啟多語句支持: multiStatements=true

(2)

SELECT *  FROM `dict_plugin`  limit  20 ,10;
SELECT count(*) as  totalCount  from `dict_plugin`;

將會形成2個數據集,golang的實踐如下:

results, err = p.Query(querystring)
    for results.Next() {
        err = results.Scan(&...)
    }

    if !results.NextResultSet() {
       log.ErrorF(ctx, "expected more result sets: %v", results.Err())
    }
        
    for results.Next() {
        err = results.Scan(&totalCount)
    }

既然提到了開啟client_multi_statements 有sql注入的風險,我們就展開聊一聊。

2. sql注入

我們先看下sql注入的原理:

有這樣的業務sql:

var input_name string
query: = "select  * from user where user_name='" + input_name+"'"
sql.Query(query)

如果從界面輸入的input_name="janus';delete from user;  --",會形成惡意sql:select * from user where user_name='janus';delete from user;  --' 。

這個時候,客戶端的client_multi_statements默認值為false就能于水火之間挽救數據庫:執行第一個sql之后,后面的惡意sql都不會執行。

由此可知,client_multi_statements=false,確實可以顯著降低sql注入的風險,但是還是沒有辦法避免單sql注入, 比如從界面密碼框注入' OR '1'='1 會繞過登錄認證。

query:= "select * from user where user='" + input_name +"' and  pwd='" +input_pwd +"'" 
 

select * from user where user='xxx' and pwd='' OR '1'='1'  -- 會繞過認證邏輯。

3. 參數化查詢防止sql注入

參數化查詢可以防止sql注入風險[1]

// Correct format for executing an SQL statement with parameters.

var queryStr = "SELECT * FROM `dict_plugin_Test` WHERE `plugin_name` = ?"
var args string = "55 union select * from `dict_plugin_Test`"

rows, err := db.Query(queryStr, args)

sql查詢內部會利用提供的參數1創建預編譯語句, 在運行時,實際是執行帶參的預編譯后的語句。

在服務器收到的查詢日志如下:

2024-08-13T08:07:18.922818Z   26 Connect root@localhost on tcinfra_janus_sharing using TCP/IP
2024-08-13T08:07:18.924525Z   26 Prepare SELECT * FROM `dict_plugin_Test` WHERE `plugin_name` = ?
2024-08-13T08:07:18.924671Z   26 Execute SELECT * FROM `dict_plugin_Test` WHERE `plugin_name` = '55 union select * from `dict_plugin_Test`'
2024-08-13T08:07:18.925273Z   26 Close stmt

判斷mysql數據庫開啟了查詢日志:show variables like '%general_log%';打開sql查詢日志的開關:set global general_log = on; 。

注意:參數占位符根據DBSM和驅動而有所不同,例如,Postgres 的pq驅動程序接受占位符形式是 $1而不是?。

3.1 預編譯語句

數據庫預編譯后, SQL語義結構和數據分離,這樣即使輸入包含惡意代碼,它也只會被當作數據處理,不會影響已經被解析固定的SQL語義結構。

預編譯語句包含兩次 sql交互:

①  預編譯階段(Prepare Phase):

  • 客戶端向服務器發送一個包含 SQL 語句(帶有參數占位符)的請求。
  • sql服務器對SQL 語句進行語法和語義檢查,然后對其進行預編譯,并為其分配一個標識符(Statement ID)。
  • 服務器返回一個確認響應,表示預編譯語句已經成功準備好。

②  執行階段(Execute Phase):

  • 客戶端發送執行請求,包含預編譯語句的標識符和實際參數值。
  • 服務器將參數值綁定到預編譯語句的占位符上,然后執行該語句。
  • 服務器返回執行結果(如結果集或影響的行數)。

圖示如下:

客戶端                          服務器
   |                               |
   |----預編譯語句(Prepare)------>|
   |                               |
   |<-------確認響應(OK)----------|
   |                               |
   |---執行語句(Execute) + 參數---->|
   |                               |
   |<----------查詢結果-------------|

我們了解到預編譯語句,將SQL語義和數據分離,通過兩次sql交互(在預編譯階段固定了sql語義結構), 有效防止了SQL注入攻擊, 另一方面,預編譯語句在重復執行某一sql語句時確實有加快查詢結果的效果。

golang的預編譯的寫法與常規的sql查詢類似:

stmt, err := p.Prepare("SELECT * FROM `dict_plugin_Test` WHERE `plugin_name` = ?")
var args string = "55 union select * from `dict_plugin_Test`"
results, err := stmt.Query(args)
if err != nil {
        fmt.Printf("query fail: %v", err)
        return err
}
defer stmt.Close()

for results.Next() {
    err = results.Scan(.....)
    ......
}

btw, C#  其實也支持預編譯語句版本的sqlCommand:SqlCommand.Prepare()

總結

本文通過我們最初開始數據庫編程時的一個實踐, 提出在【一次sql請求中執行多次sql查詢】的猜想;

了解到client_multi_statements= false 確實能避免一部分sql注入風險;

之后落地到sql注入的原理, 給出了參數化查詢(預編譯語句)能防止sql注入的核心機制。

參考資料

[1]參數化查詢可以防止sql注入風險: https://go.dev/doc/database/sql-injection

責任編輯:武曉燕 來源: 精益碼農
相關推薦

2024-09-22 14:17:54

2024-06-12 08:36:25

2024-12-02 09:57:43

GormScopesClauses

2024-01-18 09:38:00

Java注解JDK5

2024-04-28 08:24:27

分布式架構Istio

2023-03-28 07:36:01

SQL數據庫管理

2024-01-19 08:25:38

死鎖Java通信

2024-02-04 00:00:00

Effect數據組件

2023-07-26 13:11:21

ChatGPT平臺工具

2023-01-10 08:43:15

定義DDD架構

2024-01-11 08:21:33

Jetpack數據技術

2023-09-06 11:31:24

MERGE用法SQL

2022-09-29 08:32:14

查詢語句OR

2023-06-05 08:29:46

HTMLWebViewJavaScript

2023-07-10 08:36:21

工具pptword

2023-10-10 11:04:11

Rust難點內存

2024-05-06 00:00:00

InnoDBView隔離

2024-07-31 08:39:45

Git命令暫存區

2023-01-30 09:01:54

圖表指南圖形化

2024-08-06 09:47:57

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久国色| 亚洲一区欧美一区 | 亚洲视频免费在线观看 | 自拍视频一区二区三区 | 亚洲精品视频一区 | 国产美女视频黄a视频免费 国产精品福利视频 | 免费看黄视频网站 | 在线精品一区二区三区 | 欧美一级片黄色 | 日韩欧美亚洲一区 | 伊人性伊人情综合网 | 欧美综合国产精品久久丁香 | 婷婷激情五月网 | 国产免费又色又爽又黄在线观看 | 免费黄色片视频 | 成人av鲁丝片一区二区小说 | 亚洲一区二区精品视频 | 久久精品一 | 精品无码久久久久久久动漫 | 中文字幕视频在线观看 | 99久久久久久久 | 中文字幕日韩欧美一区二区三区 | 999免费网站 | 亚洲久久在线 | 一区在线播放 | 午夜视频精品 | 日韩在线一区二区三区 | 国产精品国产自产拍高清 | 中文字幕视频在线观看 | 91色视频在线 | 在线免费av电影 | 中文字幕在线一区二区三区 | 亚洲视频在线观看 | 日日摸日日碰夜夜爽2015电影 | 特级一级黄色片 | 国产精品成人一区二区三区夜夜夜 | 请别相信他免费喜剧电影在线观看 | 国产日韩欧美中文 | 免费激情网站 | 久久国产一区二区三区 | 羞视频在线观看 |