Go1.25 新特性:引入 WaitGroup.Go 和 CSRF 等方法,提升安全性!
今天帶了 2 個(gè)日常可能會(huì)接觸到的新版本小特性,開發(fā)經(jīng)常用到。對(duì)大家應(yīng)該會(huì)有所幫助。
sync:新增 WaitGroup.Go
問題背景
Go 這一門編程語言最大的特性之一就是:并發(fā)。非常好寫并發(fā),剛?cè)腴T都能寫。
而在傳統(tǒng) Go 并發(fā)代碼中,需要使用 sync.WaitGroup 協(xié)調(diào)多個(gè) goroutine 去編寫代碼。
例子如下:
var wg sync.WaitGroup
for i := 1; i <= 5; i++ {
i := i
wg.Add(1)
go func() {
defer wg.Done()
work(i)
}()
}
wg.Wait()這段代碼看似簡單,但也容易出錯(cuò)。
例如:wg.Add 必須在啟動(dòng) goroutine 前調(diào)用、必須調(diào)用 wg.Done(),同時(shí) Go1.22 之前還存在 for 循環(huán)變量閉包等常見 “陷阱”。
新提案
因此為了優(yōu)化這個(gè)場景,社區(qū)里的同學(xué) @Olivier Mengué 提出了《sync: add WaitGroup.Go[1]》的新提案:
圖片
提案本身并不復(fù)雜。核心的訴求就是增加一個(gè)新的方法 wg.Go:
func (wg *WaitGroup) Go(task func()) {
wg.Add(1)
go func() {
defer wg.Done()
task()
}()
}借助新的方案,可以將以往的方法簡化成:
var wg WaitGroup
for i := 1; i <= 5; i++ {
i := i // avoid loopvar footgun for go < 1.22
wg.Go(func() {
work(i)
})
}
wg.Wait()這么一看,用起來省力不少。
社區(qū)反饋
結(jié)合社區(qū) issues 反饋中,大家也建議將 WaitGroup 的設(shè)計(jì)重心由 “計(jì)數(shù)器” 轉(zhuǎn)變?yōu)?“任務(wù)集合”,也就是文檔中主推 wg.Go 方法使用方式。
這個(gè)提案在 Go1.25 落地后是非常不錯(cuò)的,因?yàn)榭梢匀サ麸@式 Add, defer 和 Done 結(jié)構(gòu),代碼更簡潔。
另外也可以避免 Add 放錯(cuò)位置、忘寫 Done,以及避免 Go 老版本中的閉包捕獲錯(cuò)誤等問題。
net/http:新增 CrossOriginForgeryHandler
最近 HW 行為也差不多告一段落了。這個(gè)特性還是多多少少對(duì)未來安全訴求有點(diǎn)作用的。但就是得等新版本了。
問題背景
@Filippo Valsorda 希望在 net/http 包中添加一個(gè)原生的 CSRF 防護(hù)處理器,以幫助開發(fā)者應(yīng)對(duì)跨站請(qǐng)求偽造(CSRF)攻擊。
其指出瀏覽器在請(qǐng)求中會(huì)帶上 Origin 頭,從而我們可以基于該頭進(jìn)行來源校驗(yàn),但在實(shí)際操作中他遇到了一些問題點(diǎn):
- 應(yīng)用自身的
origin識(shí)別復(fù)雜(例如:反向代理存在差異)。 - 需要開發(fā)者手動(dòng)配置
origin,增加開發(fā)與部署復(fù)雜度。
新提案
因此其提出新提案:《net/http: add CrossOriginForgeryHandler[2]》,希望引入一種標(biāo)準(zhǔn)化處理機(jī)制來簡化這個(gè)場景。
圖片
提案核心是:引入一個(gè)新類型或中間件函數(shù),例如:CrossOriginForgeryHandler,用于檢查請(qǐng)求的 Origin 或 Fetch Metadata,如 Sec-Fetch-Site。也就是類似攔截器了。
默認(rèn)情形下,設(shè)計(jì)上該 handler 能自動(dòng)拒絕非安全請(qǐng)求源(如跨站 POST 請(qǐng)求),并支持配置應(yīng)用自身的 origin 或自定義策略。
例子
新提案中的 CrossOriginForgeryHandler 函數(shù)簽名如下:
// CrossOriginForgeryHandler rejects with a 403 Forbidden any non-safe browser
// requests that were initiated from a different origin. It protects against
// ...
type CrossOriginForgeryHandler struct {
// Handler is invoked for same-origin or non-browser requests.
Handler Handler
// ErrorHandler is invoked for cross-origin requests.
// If nil, a 403 Forbidden response is returned.
ErrorHandler Handler
// BypassOrigins is a list of origins that are allowed to send cross-origin
// requests. The values in this list must be fully-formed origins, including
// the scheme, and are compared verbatim to the [Origin] header.
//
// More complex bypass rules cam be implemented with [UnsafeAllowCrossOrigin].
//
// [Origin]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin
BypassOrigins []string
}
// UnsafeAllowCrossOrigin disables [CrossOriginForgeryHandler] for the request.
// It is generally only useful when implementing single sign-on (SSO) flows.
func UnsafeAllowCrossOrigin(r *http.Request) *http.Request示例代碼如下:
func ExampleUnsafeAllowCrossOrigin() {
mux := NewServeMux()
// 注冊(cè)其他安全敏感的路由
// ...
// 啟用 CSRF 校驗(yàn),注冊(cè) CrossOriginForgeryHandler 攔截器,
csrfHandler := CrossOriginForgeryHandler{Handler: mux}
h := HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/sso/redirect" {
// 關(guān)閉校驗(yàn),顯式放行該 URL,跳過 CSRF 校驗(yàn)
r = UnsafeAllowCrossOrigin(r)
}
csrfHandler.ServeHTTP(w, r)
})
http.ListenAndServe(":8080", h)
}社區(qū)反饋
社區(qū)普遍認(rèn)可 CSRF 是一個(gè)典型需求場景,但是現(xiàn)在 Go 標(biāo)準(zhǔn)庫缺少開箱即用的防護(hù)中間件。
目前該提案已經(jīng) Accepted+Closed 并進(jìn)入到 Go1.25 的里程碑中。
圖片
相信新版本大家大概率可以用到啦!
總結(jié)
本次給大家介紹的 Go1.25 新特性:WaitGroup.Go 和 CrossOriginForgeryHandler 的 CSRF 的防御增強(qiáng)。
雖然不是特別大的特性,但是他與我們的日常開發(fā)工作很接近,甚至可以直接融入開發(fā)中。還是挺不錯(cuò)的。
參考資料
[1] sync: add WaitGroup.Go: https://github.com/golang/go/issues/63796
[2] net/http: add CrossOriginForgeryHandler: https://github.com/golang/go/issues/73626


































