Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 97av视频在线播放,在线观看视频你懂的,日本视频一区二区三区

          整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          Go語言SQL注入和防注入

          Go語言SQL注入和防注入

          、SQL注入是什么

          SQL注入是一種注入攻擊手段,通過執(zhí)行惡意SQL語句,進(jìn)而將任意SQL代碼插入數(shù)據(jù)庫查詢,從而使攻擊者完全控制Web應(yīng)用程序后臺的數(shù)據(jù)庫服務(wù)器。攻擊者可以使用SQL注入漏洞繞過應(yīng)用程序驗(yàn)證,比如繞過登錄驗(yàn)證登錄Web身份驗(yàn)證和授權(quán)頁面;也可以繞過網(wǎng)頁,直接檢索數(shù)據(jù)庫的所有內(nèi)容;還可以惡意修改、刪除和增加數(shù)據(jù)庫內(nèi)容。

          二、防止SQl注入的思路和方法

          • 1.永遠(yuǎn)不要信任用戶的輸入。對用戶的輸入進(jìn)行校驗(yàn),可以通過正則表達(dá)式,或限制長度;對單引號和 雙"-"進(jìn)行轉(zhuǎn)換等。
          • 2.永遠(yuǎn)不要使用動(dòng)態(tài)拼裝SQL,可以使用參數(shù)化的SQL或者直接使用存儲過程進(jìn)行數(shù)據(jù)查詢存取。
          • 3.永遠(yuǎn)不要使用管理員權(quán)限的數(shù)據(jù)庫連接,為每個(gè)應(yīng)用使用單獨(dú)的權(quán)限有限的數(shù)據(jù)庫連接。
          • 4.不要把機(jī)密信息直接存放,加密或者h(yuǎn)ash掉密碼和敏感的信息。
          • 5.應(yīng)用的異常信息應(yīng)該給出盡可能少的提示,最好使用自定義的錯(cuò)誤信息對原始錯(cuò)誤信息進(jìn)行包裝
          • 6.sql注入的檢測方法一般采取輔助軟件或網(wǎng)站平臺來檢測,軟件一般采用sql注入檢測工具jsky,網(wǎng)站平臺就有億思網(wǎng)站安全平臺檢測工具。MDCSOFT SCAN等。采用MDCSOFT-IPS可以有效的防御SQL注入,XSS攻擊等。

          三、Go語言防止SQL注入的方法

          我們采取了第二條思路和方法,即不用動(dòng)態(tài)拼接SQL語句的方法,而是使用參數(shù)化查詢,即變量綁定。

          下面給出SQL注入攻擊安全漏洞代碼——拼接SQL語句:

          //數(shù)據(jù)庫
          /*
           Navicat Premium Data Transfer
          
           Source Server         : localhost_3306
           Source Server Type    : MySQL
           Source Server Version : 50553
           Source Host           : localhost:3306
           Source Schema         : test
          
           Target Server Type    : MySQL
           Target Server Version : 50553
           File Encoding         : 65001
          
           Date: 28/02/2020 10:48:06
          */
          
          SET NAMES utf8mb4;
          SET FOREIGN_KEY_CHECKS=0;
          
          -- ----------------------------
          -- Table structure for userinfo
          -- ----------------------------
          DROP TABLE IF EXISTS `userinfo`;
          CREATE TABLE `userinfo`  (
            `uid` int(10) NOT NULL AUTO_INCREMENT,
            `username` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
            `password` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
            PRIMARY KEY (`uid`) USING BTREE
          ) ENGINE=MyISAM AUTO_INCREMENT=14 CHARACTER SET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=Dynamic;
          
          -- ----------------------------
          -- Records of userinfo
          -- ----------------------------
          INSERT INTO `userinfo` VALUES (2, 'aaa', 'hh');
          INSERT INTO `userinfo` VALUES (4, 'ast', 'dddd');
          
          SET FOREIGN_KEY_CHECKS=1;
          
          
          //test.go
          package main
          
          import (
          	"database/sql"
          	"fmt"
          	_ "github.com/go-sql-driver/mysql"
          	"html/template"
          	"log"
          	"net/http"
          	"strings"
          )
          func login(w http.ResponseWriter, r *http.Request) {
          	fmt.Println("method:", r.Method) //獲取請求的方法
          	if r.Method=="GET" {
          		t, _ :=template.ParseFiles("D:/Golang/GoItem/go_ex/goSql/test.html")
          		t.Execute(w, nil)
          	} else {
          		//請求的是查詢數(shù)據(jù),那么執(zhí)行查詢的邏輯判斷
          		r.ParseForm()
          		fmt.Println("username:", r.Form["username"])
          		var sename=strings.Join(r.Form["username"], "")
          		var partname=strings.Join(r.Form["password"], "")
          		db, err :=sql.Open("mysql", "root:123456@/test?charset=utf8")
          		infoErr(err)
          		if sename !="" && partname !="" {
          			var uid int
          			var username string
          			var password string
          			//字符串拼接查詢
          			err :=db.QueryRow("SELECT * FROM userinfo WHERE username='"+sename+"'AND password='"+partname+"'").
          				Scan(&uid, &username, &password)
          			infoErr(err)
          			//判斷返回的數(shù)據(jù)是否為空
          			if err==sql.ErrNoRows {
          				fmt.Fprintf(w, "無該用戶數(shù)據(jù)")
          			} else {
          				if (sename==username) && (partname==password) {
          					fmt.Println(uid)
          					fmt.Println(username)
          					fmt.Println(password)
          					t, _ :=template.ParseFiles("D:/Golang/GoItem/go_ex/goSql/success.html")
          					t.Execute(w, nil)
          				}
          			}
          		} else if sename=="" || partname=="" {
          			fmt.Fprintf(w, "錯(cuò)誤,輸入不能為空!")
          		}
          
          	}
          
          }
          
          
          func infoErr(err error) {
          	if err !=nil {
          		panic(err)
          	}
          }
          
          func main() {
          	http.HandleFunc("/login",login)     //設(shè)置訪問的路由 	//設(shè)置訪問的路由
          	err :=http.ListenAndServe(":9092", nil) //設(shè)置監(jiān)聽的端口
          	if err !=nil {
          		log.Fatal("ListenAndServe: ", err)
          	}
          }
          
          //login.html
          <html>
          <head>
              <meta charset="utf-8" />
              <title>sql防注入</title>
              <style>
                  form{
                      width: 30vw;
                      height: 30vh;
                      min-height: 300px;
                      margin: 10vh auto;
                      border: 1px solid;
                      border-radius: 4px;
                  }
                  form .username,.password{
                     display: block;
                      float: right;
                  }
                  div {
                      width: 300px;
                      height: 80px;
                      margin: 30px auto 0;
                  }
                  input label {
                      float: left;
                      display: inline-block;
                  }
                  input {
                      height: 30px;
                  }
                  .button {
                      width: 100px;
                      margin: auto;
                      clear: both;
                      display: block;
                  }
              </style>
          </head>
          <body>
          <form action="/login" method="post">
              <div>
                  <label>username: </label>
                  <input class="username" type="text" name="username">
              </div>
              <div>
                  <label>password:</label>
                  <input class="password" type="text" name="password">
              </div>
              <input class="button" type="submit" value="查詢">
          </form>
          </body>
          </html>
          

          解決防SQL注入方案——參數(shù)化查詢:

          //test.go
          package main
          
          import (
          	"database/sql"
          	"fmt"
          	_ "github.com/go-sql-driver/mysql"
          	"html/template"
          	"log"
          	"net/http"
          	"strings"
          )
          
          func login(w http.ResponseWriter, r *http.Request) {
          	fmt.Println("method:", r.Method) //獲取請求的方法
          	if r.Method=="GET" {
          		t, _ :=template.ParseFiles("D:/Golang/GoItem/go_ex/goSql/login.html")
          		t.Execute(w, nil)
          	} else {
          		//請求的是查詢數(shù)據(jù),那么執(zhí)行查詢的邏輯判斷
          		r.ParseForm()
          		fmt.Println("username:", r.Form["username"])
          		var sename=strings.Join(r.Form["username"], "")
          		var partname=strings.Join(r.Form["password"], "")
          		db, err :=sql.Open("mysql", "root:123456@/test?charset=utf8")
          		checkErr(err)
          		if sename !="" && partname !="" {
          			var uid int
          			var username string
          			var password string
                      //參數(shù)查詢在一定程度上防止sql注入,參數(shù)化查詢主要做了兩件事:
          			//1.參數(shù)過濾;2.執(zhí)行計(jì)劃重用
          			//因?yàn)閳?zhí)行計(jì)劃被重用,所以可以防止SQL注入。
          			err :=db.QueryRow("SELECT * FROM userinfo WHERE username=? AND password=?", sename, partname).
          				Scan(&uid, &username, &password)
          			//判斷返回的數(shù)據(jù)是否為空
          			if err==sql.ErrNoRows {
          				fmt.Fprintf(w, "無該用戶數(shù)據(jù)")
          			} else {
          				if (sename==username) && (partname==password) {
          					fmt.Println(uid)
          					fmt.Println(username)
          					fmt.Println(password)
          					t, _ :=template.ParseFiles("D:/Golang/GoItem/go_ex/goSQL/success.html")
          					t.Execute(w, nil)
          				}
          			}
          		} else if sename=="" || partname=="" {
          			fmt.Fprintf(w, "錯(cuò)誤,輸入不能為空!")
          		}
          
          	}
          
          }
          
          func checkErr(err error) {
          	if err !=nil {
          		panic(err)
          	}
          }
          
          func main() {
          	http.HandleFunc("/login", login)     //設(shè)置訪問的路由
          	err :=http.ListenAndServe(":9090", nil) //設(shè)置監(jiān)聽的端口
          	if err !=nil {
          		log.Fatal("ListenAndServe: ", err)
          	}
          }
          
          

          四、SQL注入判斷

          執(zhí)行登錄查詢的數(shù)據(jù)庫語句:"SELECT * FROM userinfo WHERE username='"+sename+"'AND password='"+partname+"'"

          當(dāng)查詢到數(shù)據(jù)表中存在同時(shí)滿足 username 和 password 字段時(shí),會返回用戶信息。 嘗試在用戶名中輸入 123' or 1=1 #, 密碼同樣輸入 123' or 1=1 # ,實(shí)際執(zhí)行的SQL語句是select * from users where username='123' or '1'='1' and password='123' or '1'='1

          則會出現(xiàn)一個(gè)空白頁面,其實(shí)此時(shí)SQl注入已經(jīng)繞過驗(yàn)證進(jìn)入到需要身份驗(yàn)證的頁面。

          而如果執(zhí)行"SELECT * FROM userinfo WHERE username=? AND password=?", sename, partname

          再次輸入123' or 1=1 #,則會被攔截下來,顯示無該用戶數(shù)據(jù)

          五、為什么參數(shù)化查詢會防止SQL注入

          我們需要知道參數(shù)化查詢都做了些什么事:

          1.參數(shù)過濾

          2.執(zhí)行計(jì)劃重用

          它的原理是采用了預(yù)編譯的方法,先將SQL語句中可被客戶端控制的參數(shù)集進(jìn)行編譯,生成對應(yīng)的臨時(shí)變量集,再使用對應(yīng)的設(shè)置方法,為臨時(shí)變量集里面的元素進(jìn)行賦值,而QueryRow()方法會對傳入?yún)?shù)進(jìn)行強(qiáng)制類性檢查和安全檢查,所以就避免了SQL注入的產(chǎn)生。

          package main
          import (
              "fmt"
              "net/http"
              "sync"
              "github.com/PuerkitoBio/goquery"
          )
          func main() {
              // 定義urls數(shù)組,包含要爬取的多個(gè)網(wǎng)頁的URL
              urls :=[]string{
                  "https://www.xp.cn/using.html",
                  "https://www.xp.cn/advise.html",
                  "https://www.xp.cn/bug.html",
              }
              // WaitGroup來等待所有的goroutine執(zhí)行完畢
              var wg sync.WaitGroup
              for _, url :=range urls {
                  wg.Add(1)
                  // 用goroutine來同時(shí)爬取這些網(wǎng)頁
                  go func(u string) {
                      defer wg.Done()
                      resp, err :=http.Get(u)
                      if err !=nil {
                          fmt.Println(err)
                          return
                      }
                      defer resp.Body.Close()
                      // 解析網(wǎng)頁內(nèi)容
                      doc, err :=goquery.NewDocumentFromReader(resp.Body)
                      if err !=nil {
                          fmt.Println(err)
                          return
                      }
                      // 獲取標(biāo)題
                      doc.Find(".pb-20").Each(func(i int, s *goquery.Selection) {
                          title :=s.Find("li div a").Text()
                          fmt.Printf("%s\n", title)
                      })
                  }(url)
              }
              wg.Wait()
          }

          實(shí)際應(yīng)用中,我們還可以通過設(shè)置代理、使用cookie等方式來提高爬取效率和穩(wěn)定性。

          爬取汽車之家網(wǎng)站的車型數(shù)據(jù),您需要先了解該網(wǎng)站的頁面結(jié)構(gòu)和數(shù)據(jù)源。一般來說,您可以使用Go語言中的HTTP客戶端庫(如net/http)和HTML解析器(如goquery)來實(shí)現(xiàn)爬取。

          以下是一個(gè)簡單的示例代碼,它可以爬取汽車之家網(wǎng)站上所有品牌的車型數(shù)據(jù):

          package main
          
          import (
          	"fmt"
          	"log"
          	"net/http"
          	"strings"
          
          	"github.com/PuerkitoBio/goquery" // 導(dǎo)入 goquery 庫,用于解析 HTML 頁面
          )
          
          func main() {
          	url :="https://www.autohome.com.cn/grade/carhtml/"
          
          	// 發(fā)送 HTTP GET 請求獲取頁面內(nèi)容
          	res, err :=http.Get(url)
          	if err !=nil {
          		log.Fatal(err)
          	}
          	defer res.Body.Close()
          
          	// 檢查狀態(tài)碼是否為 200
          	if res.StatusCode !=200 {
          		log.Fatalf("Status code error: %d %s", res.StatusCode, res.Status)
          	}
          
          	// 使用 goquery 解析頁面內(nèi)容
          	doc, err :=goquery.NewDocumentFromReader(res.Body)
          	if err !=nil {
          		log.Fatal(err)
          	}
          
          	// 遍歷頁面中所有的 <dl> 元素
          	doc.Find("dl").Each(func(i int, s *goquery.Selection) {
          		// 提取品牌名稱
          		brand :=s.Find("dt").Text()
          		brand=strings.TrimSpace(brand)
          		if brand !="" {
          			fmt.Println(brand)
          			// 遍歷該品牌下的所有車型
          			s.Find("dd a").Each(func(j int, t *goquery.Selection) {
          				model :=t.Text()
          				model=strings.TrimSpace(model)
          				if model !="" {
          					fmt.Printf("  %s\n", model)
          				}
          			})
          		}
          	})
          }
          

          注釋已添加在代碼中。該代碼使用 http.Get() 函數(shù)發(fā)送 HTTP GET 請求,并使用 goquery.NewDocumentFromReader() 函數(shù)解析 HTML 頁面內(nèi)容。然后,代碼遍歷頁面中所有的 <dl> 元素,提取品牌名稱和車型名稱,并將它們打印到控制臺中。

          需要注意的是,這里只是簡單地打印車型數(shù)據(jù)到控制臺,實(shí)際使用時(shí)可能需要進(jìn)行更多的處理,例如將數(shù)據(jù)保存到數(shù)據(jù)庫或文件中。此外,還需要遵守網(wǎng)站的使用條款和限制,不要過度訪問或?yàn)E用網(wǎng)站資源。


          主站蜘蛛池模板: 无码人妻精品一区二区三区9厂| 亚洲性无码一区二区三区| 一区一区三区产品乱码| 国产一区二区三区在线看片| 日本伊人精品一区二区三区| 又紧又大又爽精品一区二区| 亚无码乱人伦一区二区| 99久久精品国产一区二区成人| 成人乱码一区二区三区av| 日本福利一区二区| 免费一本色道久久一区| 国产日韩一区二区三区| 亚洲丰满熟女一区二区v| 久久精品一区二区三区四区| 精品国产日产一区二区三区 | 无遮挡免费一区二区三区| 日韩精品国产一区| 国产拳头交一区二区| 国产伦精品一区二区三区视频小说| 欧美成人aaa片一区国产精品| 亚洲AV无码一区二区三区网址| 亚洲日本va一区二区三区| 亚洲午夜在线一区| 男人的天堂av亚洲一区2区| 日韩精品一区二区三区中文版 | 国产精品电影一区二区三区| 精品国产一区二区三区在线| 精品国产一区二区三区在线| 人成精品视频三区二区一区 | 国产亚洲一区二区手机在线观看| 国产精品男男视频一区二区三区| 香蕉在线精品一区二区| 亚洲熟妇av一区二区三区| 日韩精品在线一区二区| 亚洲日本久久一区二区va| 综合一区自拍亚洲综合图区| 日亚毛片免费乱码不卡一区| 福利一区二区三区视频在线观看| 麻豆国产一区二区在线观看 | 久久国产精品最新一区| 亚洲熟妇AV一区二区三区宅男|