目錄
- 一 點睛
- 二 先看一個轉義的例子
- 三 使用 text/template 進行處理
- 四 使用 html/template 進行處理
一 點睛
現在的網站包含大量的動態內容以提高用戶體驗,比過去要復雜得多。所謂動態內容,就是根據用戶環境和需要,Web 應用程序能夠輸出相應的內容。動態站點會受到一種名為“跨站腳本攻擊”(Cross Site Scripting, 安全專家們通常將其縮寫成 XSS)的威脅,而靜態站點則完全不受其影響。
攻擊者通常會在有漏洞的程序中插入 JavaScript、VBScript、 ActiveX 或 Flash 以欺騙用戶。一旦得手,他們可以盜取用戶帳戶信息,修改用戶設置,盜取或污染 cookie 和植入惡意廣告等。
對 XSS 最佳的防護應該結合以下兩種方式。
1 驗證所有輸入數據,有效檢測攻擊。
2 對所有輸出數據進行適當的處理,以防止任何已成功注入的腳本在瀏覽器端運行。
針對第2種方式,Go 是怎樣預防的呢?Go 的 html/template 包中帶有下面幾個函數可以幫助轉義。
func HTMLEscape(w io.Writer, b []byte) // 把 b 進行轉義之后寫到 w
func HTMLEscapeString(s string) string // 轉義 s 之后返回結果字符串
func HTMLEscaper(args ...interface{}) string // 支持多個參數一起轉義,返回結果字符串
二 先看一個轉義的例子
1 代碼
package main
import (
"fmt"
"html/template"
"log"
"net/http"
)
// 登錄邏輯
func login(w http.ResponseWriter, r *http.Request) {
fmt.Println("method:", r.Method) // 獲取請求的方法
if r.Method == "GET" {
t, _ := template.ParseFiles("src\\goweb\\demo3\\login.html") // 解析模板
t.Execute(w, nil) // 渲染模板,并發送給前端
} else {
// 請求的是登陸數據,那么執行登陸的邏輯判斷
// 解析表單
r.ParseForm()
fmt.Println("username:", r.Form["username"])
fmt.Println("password:", r.Form["password"])
template.HTMLEscape(w, []byte(r.Form.Get("username"))) //輸出到客戶端
}
}
func main() {
http.HandleFunc("/login", login) // 設置訪問的路由
err := http.ListenAndServe(":9090", nil) // 設置監聽的端口
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
2 測試
如果在瀏覽器輸入的 username 是 script>alert()/script>,在瀏覽器上將看到下面內容。

3 說明
Go 的 html/template 包默認幫忙過濾了 html 標簽,將其進行了轉義。
4 問題引出
如果要正常輸出script>alert()/script>,怎樣處理呢?text/template 可以幫忙進行處理。
三 使用 text/template 進行處理
1 代碼
package main
import (
"log"
"net/http"
"text/template"
)
// 轉義測試
func escape(w http.ResponseWriter, r *http.Request) {
// 正常顯示
t, _ := template.New("foo").Parse(`{{define "T"}}Hello1, {{.}}!{{end}}`)
t.ExecuteTemplate(w, "T", "script>alert('you have been pwned')/script>")
}
func main() {
http.HandleFunc("/escape", escape) // 設置轉義
err := http.ListenAndServe(":9090", nil) // 設置監聽的端口
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
2 測試

3 說明
當使用 text/template 這個包時,可以正常顯示。
四 使用 html/template 進行處理
1 代碼
package main
import (
"html/template"
"log"
"net/http"
)
// 轉義測試
func escape(w http.ResponseWriter, r *http.Request) {
// 轉義顯示
t, _ := template.New("foo").Parse(`{{define "T"}}Hello1, {{.}}!{{end}}`)
t.ExecuteTemplate(w, "T", "script>alert('you have been pwned')/script>")
// 正常顯示
t, _ = template.New("foo").Parse(`{{define "T"}}Hello2, {{.}}!{{end}}`)
t.ExecuteTemplate(w, "T", template.HTML("script>alert('you have been pwned')/script>"))
}
func main() {
http.HandleFunc("/escape", escape) // 設置轉義
err := http.ListenAndServe(":9090", nil) // 設置監聽的端口
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
2 測試結果

3 說明
當使用 html/template 這個包時,如果使用 template.HTML 函數,也可以正常顯示,不使用 template.HTML 函數,轉義顯示。
以上就是go web 預防跨站腳本的詳細內容,更多關于go web 預防跨站的資料請關注腳本之家其它相關文章!
您可能感興趣的文章:- Python+Django+MySQL實現基于Web版的增刪改查的示例代碼
- 詳解Django3中直接添加Websockets方式
- python+Django+pycharm+mysql 搭建首個web項目詳解
- 使用Django搭建web服務器的例子(最最正確的方式)
- Django CSRF跨站請求偽造防護過程解析
- Django中如何防范CSRF跨站點請求偽造攻擊的實現