Go語言中如何確保Cookie數(shù)據(jù)的安全傳輸
什么是Cookie
Cookie(也叫Web Cookie或瀏覽器Cookie)是服務器發(fā)送到用戶瀏覽器并保存在本地的一小塊數(shù)據(jù),它會在瀏覽器下次向同一服務器再發(fā)起請求時被攜帶并發(fā)送到服務器上。通常,它用于告知服務端兩個請求是否來自同一瀏覽器,如保持用戶的登錄狀態(tài)。Cookie使基于無狀態(tài)的HTTP協(xié)議記錄穩(wěn)定的狀態(tài)信息成為了可能。
Cookie主要用于以下三個方面:
- 會話狀態(tài)管理(如用戶登錄狀態(tài)、購物車、游戲分數(shù)或其它需要記錄的信息)
- 個性化設置(如用戶自定義設置、主題等)
- 瀏覽器行為跟蹤(如跟蹤分析用戶行為等)
Go語言如何表示Cookie
在Go的net/http庫中使用http.Cookie結構體表示一個Cookie數(shù)據(jù),調用http.SetCookie函數(shù)則會告訴終端用戶的瀏覽器把給定的http.Cookie值設置到瀏覽器Cookie里,類似下面:
func someHandler(w http.ResponseWriter, r *http.Request) { c := http.Cookie{ Name: "UserName", Value: "Casey", } http.SetCookie(w, &c) }
http.Cookie結構體類型的定義如下:
type Cookie struct { Name string Value string Path string // optional Domain string // optional Expires time.Time // optional RawExpires string // for reading cookies only // MaxAge=0 means no 'Max-Age' attribute specified. // MaxAge<0 means delete cookie now, equivalently 'Max-Age: 0' // MaxAge>0 means Max-Age attribute present and given in seconds MaxAge int Secure bool HttpOnly bool SameSite SameSite Raw string Unparsed []string // Raw text of unparsed attribute-value pairs }
Name和Value字段就不多說了,單獨針對幾個需要解釋的字段進行說明。
Domain
默認值是當前正在訪問的Host的域名,假設我們現(xiàn)在正在訪問的是www.example.com,如果需要其他子域名也能夠訪問到正在設置的Cookie值的話,將它設置為example.com 。注意,只有正在被設置的Cookie需要被其他子域名的服務訪問到時才這么設置。
c := Cookie{ ...... Domain: "example.com", }
Path
設置當前的 Cookie 值只有在訪問指定路徑時才能被服務器程序讀取。默認為服務端應用程序上的任何路徑,但是您可以使用它限制為特定的子目錄。例如:
c := Cookie{ Path: "/app/", }
Secure
標記為Secure 的Cookie只應通過被HTTPS協(xié)議加密過的請求發(fā)送給服務端。但即便設置了 Secure 標記,敏感信息也不應該通過Cookie傳輸,因為Cookie有其固有的不安全性,Secure 標記也無法提供確實的安全保障。從 Chrome 52 和 Firefox 52 開始,不安全的站點(http:)無法使用Cookie的 Secure 標記。
HttpOnly
為避免跨域腳本 (XSS) 攻擊,通過JavaScript的API無法訪問帶有 HttpOnly 標記的Cookie,它們只應該發(fā)送給服務端。如果包含服務端Session 信息的Cookie 不想被客戶端JavaScript 腳本調用,那么就應該為其設置 HttpOnly 標記。
安全地傳輸Cookie
接下來我們探討兩種安全傳輸Cookie的方法
對Cookie數(shù)據(jù)進行數(shù)字簽名
對數(shù)據(jù)進行數(shù)字簽名是在數(shù)據(jù)上添加“簽名”的行為,以便可以驗證其真實性。不需要對數(shù)據(jù)進行加密或屏蔽。
簽名的工作方式是通過散列-我們對數(shù)據(jù)進行散列,然后將數(shù)據(jù)與數(shù)據(jù)散列一起存儲在Cookie中。然后,當用戶將Cookie發(fā)送給我們時,我們再次對數(shù)據(jù)進行哈希處理,并驗證其是否與我們創(chuàng)建的原始哈希匹配。
我們不希望用戶也用篡改后的數(shù)據(jù)創(chuàng)建新的哈希,因此經常會看到使用HMAC之類的哈希算法,以便可以使用密鑰對數(shù)據(jù)進行哈希。這樣可以防止最終用戶同時編輯數(shù)據(jù)和數(shù)字簽名(哈希)。
JWT也是使用的這種數(shù)字簽名的方式進行傳輸?shù)摹?/p>
上面的數(shù)據(jù)簽名過程并不需要我們自己去實現(xiàn),我們可以在Go中使用gorilla/securecookie的程序包來完成此操作,在該程序包中,你可以在創(chuàng)建SecureCookie時為其提供哈希密鑰,然后使用該對象來保護你的Cookie。
對Cookie數(shù)據(jù)進行簽名:
//var s = securecookie.New(hashKey, blockKey) var hashKey = securecookie.GenerateRandomKey(64) var s = securecookie.New(hashKey, nil) func SetCookieHandler(w http.ResponseWriter, r *http.Request) { encoded, err := s.Encode("cookie-name", "cookie-value") if err == nil { cookie := &http.Cookie{ Name: "cookie-name", Value: encoded, Path: "/", } http.SetCookie(w, cookie) fmt.Fprintln(w, encoded) }
解析被簽名的 Cookie:
func ReadCookieHandler(w http.ResponseWriter, r *http.Request) { if cookie, err := r.Cookie("cookie-name"); err == nil { var value string if err = s.Decode("cookie-name", cookie.Value, &value); err == nil { fmt.Fprintln(w, value) } } }
注意這里的Cookie數(shù)據(jù)未加密,僅僅是被編碼了,任何人都可以把Cookie數(shù)據(jù)解碼回來。
加密Cookie 數(shù)據(jù)
每當將數(shù)據(jù)存儲在Cookie中時,請始終盡量減少存儲在Cookie中的敏感數(shù)據(jù)量。不要存儲用戶密碼之類的東西,并確保任何編碼數(shù)據(jù)也沒有此信息。在某些情況下,開發(fā)人員在不知不覺中將敏感數(shù)據(jù)存儲在Cookie或JWT中,因為它們是base64編碼的,但實際上任何人都可以解碼該數(shù)據(jù)。它已編碼,未加密。
這是一個很大的錯誤,因此,如果你擔心意外存儲敏感內容,建議 你使用gorilla/securecookie之類的軟件包。
之前我們討論了如何將其用于對Cookie進行數(shù)字簽名,但是securecookie也可以用于加密和解密Cookie數(shù)據(jù),以使其無法輕松解碼和讀取。
要使用該軟件包加密Cookie,只需在創(chuàng)建SecureCookie實例時傳入一個blockKey即可。
將上面簽名Cookie的代碼片段進行一些小改動,其他地方完全不用動,securecookie包會幫助我們進行Cookie的加密和解密:
var hashKey = securecookie.GenerateRandomKey(64) var blockKey = securecookie.GenerateRandomKey(32) var s = securecookie.New(hashKey, blockKey)
總結
今天的文章除了闡述如何使用Go語言安全地傳輸Cookie數(shù)據(jù)外,再次格外強調一遍,編碼和加密的不同,從數(shù)據(jù)可讀性上看,兩者差不多,但本質上是完全不一樣的:
- 編碼使用公開可用的方案將數(shù)據(jù)轉換為另一種格式,以便可以輕松地將其反轉。
- 加密將數(shù)據(jù)轉換為另一種格式,使得只有特定的個人才能逆轉轉換。
我們在做數(shù)據(jù)傳輸時一定要記住兩者的區(qū)別,某種意義上,我覺得記住這兩點的區(qū)別比你學會今天文章里怎么安全傳輸Cookie更重要。
到此這篇關于Go語言中如何確保Cookie數(shù)據(jù)的安全傳輸?shù)奈恼戮徒榻B到這了,更多相關Go Cookie數(shù)據(jù)傳輸內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
go語言開發(fā)環(huán)境配置(sublime text3+gosublime)
網(wǎng)上google了下go的開發(fā)工具,大都推薦sublime text3+gosublime,本文就介紹了go語言開發(fā)環(huán)境配置(sublime text3+gosublime),具有一定的參考價值,感興趣的可以了解一下2022-01-01如何在golang中使用shopspring/decimal來處理精度問題
本文主要介紹了如何在golang中使用shopspring/decimal來處理精度問題,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-04-04golang使用map支持高并發(fā)的方法(1000萬次操作14ms)
這篇文章主要介紹了golang使用map支持高并發(fā)的方法(1000萬次操作14ms),本文給大家詳細講解,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-11-11