關(guān)于Gin框架中的Cookie和Session的使用方法
引言
在深入探討Cookie和Session之前,我們需要了解HTTP協(xié)議的無狀態(tài)特性。簡單來說,HTTP是一種無狀態(tài)協(xié)議,即每次請求與響應(yīng)之間都是獨立的,服務(wù)器不會記住之前的狀態(tài)信息。這意味著,當(dāng)用戶從一個頁面跳轉(zhuǎn)到另一個頁面時,服務(wù)器無法自動識別這是同一個用戶的請求。為了實現(xiàn)跨請求的數(shù)據(jù)共享,我們可以使用Cookie和Session。本文將結(jié)合實際案例,詳細(xì)介紹在Go語言的Gin框架中如何使用Cookie和Session。
一、Cookie的詳細(xì)用法
1. Cookie的基本概念
Cookie是一種存儲在客戶端瀏覽器中的鍵值對數(shù)據(jù),用于在客戶端和服務(wù)器之間傳遞信息。每次向服務(wù)器發(fā)送請求時,瀏覽器都會自動攜帶這些Cookie信息。
2. 設(shè)置Cookie
在Gin框架中,可以通過c.SetCookie方法設(shè)置Cookie。以下是該方法的主要參數(shù):
- name:Cookie的名稱。
- value:Cookie的值。
- maxAge:Cookie的過期時間(秒)。如果只想設(shè)置Cookie的保存路徑而不想設(shè)置存活時間,可以在此參數(shù)中傳遞nil。
- path:Cookie的路徑。
- domain:Cookie的域名作用域。本地調(diào)試時配置為localhost,正式上線時配置為域名。
- secure:當(dāng)此值為true時,Cookie在HTTP中是無效的,僅在HTTPS中有效。
- httpOnly:如果設(shè)置了此屬性,則通過程序(如JS腳本)將無法讀取到Cookie信息,防止XSS攻擊。
示例代碼:
package main import ( "github.com/gin-gonic/gin" ) func TestHandler(c *gin.Context) { // 獲取客戶端是否攜帶Cookie 獲取名為"username"的Cookie // 如果不存在將myCookie設(shè)為lucas mycookie, err := c.Cookie("username") if err != nil { mycookie = "lucas" } // 給客戶端設(shè)置Cookie // func (c *Context) SetCookie(name, value string, maxAge int, path, domain string, secure, httpOnly bool) c.SetCookie("username", mycookie, 60*60, "/", "localhost", false, true) //響應(yīng)客戶端字符串 c.String(200, "測試Cookie") } func main() { r := gin.Default() // 創(chuàng)建路由,默認(rèn)使用Logger()和Recovery()中間件 // func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes r.GET("/cookie", TestHandler) r.Run(":8888") }
可以看到服務(wù)端給瀏覽器客戶端設(shè)置的cookie
3. 獲取cookie
要獲取客戶端請求中的Cookie,可以使用c.Cookie()方法。以下是一個示例:
package main import ( "github.com/gin-gonic/gin" "net/http" ) func getCookie(c *gin.Context) { // 獲取名為"username"的Cookie cookie, err := c.Cookie("username") if err != nil { c.String(http.StatusOK, "未找到Cookie") return } c.String(http.StatusOK, "Cookie值:"+cookie) } func main() { r := gin.Default() r.GET("/getCookie", getCookie) r.Run(":8080") }
由于我們設(shè)置了一條cookie,username為lucas,所以能獲取到
4. 刪除Cookie
刪除Cookie實際上是通過設(shè)置其過期時間為負(fù)數(shù)來實現(xiàn)的。
package main import ( "github.com/gin-gonic/gin" "net/http" ) func deleteCookie(c *gin.Context) { // 刪除名為"username"的Cookie //實際上就是設(shè)置maxAge為負(fù)數(shù) c.SetCookie("username", "", -1, "/", "localhost", false, true) c.String(http.StatusOK, "刪除Cookie成功") } func main() { r := gin.Default() //在請求處,將handlers函數(shù)傳進(jìn)來 r.GET("/deleteCookie", deleteCookie) r.Run(":8080") }
在上面的代碼中,c.SetCookie(“username”, “”, -1, “/”, “localhost”, false, true)方法會將名為"username"的Cookie過期時間設(shè)置為過去的時間戳,從而刪除該Cookie。
二、Session的詳細(xì)用法
1. Session的基本概念
Session是一種記錄客戶狀態(tài)的機(jī)制,與Cookie不同的是,Session數(shù)據(jù)保存在服務(wù)器上。當(dāng)客戶端瀏覽器第一次訪問服務(wù)器并發(fā)送請求時,服務(wù)器端會創(chuàng)建一個Session對象,生成一個類似于key-value的鍵值對,然后將value保存到服務(wù)器,將key(通常是一個Cookie)返回到瀏覽器(客戶端)。瀏覽器下次訪問時會攜帶這個key,服務(wù)器通過這個key找到對應(yīng)的Session數(shù)據(jù)。
2. Session的工作原理
- 1: 我們的請求在默認(rèn)情況下是無狀態(tài)的,所謂的無狀態(tài)就是指,gin定義一個路由地址,在瀏覽器訪問以后,也就是
發(fā)起一個request,到response的過程,整個過程結(jié)束后,并不會在服務(wù)器端存儲數(shù)據(jù)。這樣就會造成一個問題,
無法解決各路由請求之間數(shù)據(jù)的共享問題。 - 2:如何解決這個問題呢?其實也就是session
- 3:session是一種服務(wù)器端的存儲技術(shù),其實在底層就是一個全局的map[string][any]對象。它可以把一些需要各個
路由間共享的數(shù)據(jù)進(jìn)行存儲在內(nèi)存中,直到服務(wù)器關(guān)閉或者超時才會清除。 - 4:有了session,為什么還有有sessionId呢?因為要區(qū)分是那個業(yè)務(wù)的數(shù)據(jù),因為底層是map,所以大部分情況下都會
用sessionId作為key. - 5:有了session,為啥還要cookie技術(shù)呢,cookie是一種客戶端的存儲技術(shù),在創(chuàng)建session的時候,每次都會把這個
sessionId寫入到客戶端瀏覽器的cookie中,后續(xù)給未來的每個路由請求都攜帶這個sessionId, 到服務(wù)端的map種去匹配
對應(yīng)自己的數(shù)據(jù)信息。 - 6:從而達(dá)到數(shù)據(jù)的共享。
3. Sesison的應(yīng)用場景
第一次登錄,服務(wù)器給客戶端頒發(fā)一個唯一的sessionId, 并通過http的響應(yīng)頭返回??蛻舳耍g覽器)發(fā)現(xiàn)返回的數(shù)據(jù)中有cookie數(shù)據(jù)就把這個cookie數(shù)據(jù)存放到內(nèi)存。下次再發(fā)送http請求時,把內(nèi)存中的cookie數(shù)據(jù)再塞到http請求頭中,一并發(fā)給服務(wù)器,服務(wù)器在解析請求時,發(fā)現(xiàn)請求頭中有cookie,就開始識別cookie中的sessionId,拿到sessionId,我們就知道這個請求時由哪個客戶端發(fā)送來的了。
4. 在Gin框架中使用Session
Gin框架本身并不內(nèi)置對Session的支持,但可以使用第三方的Session中間件來實現(xiàn)。其中比較常用的是github.com/gin-contrib/sessions。
1. 安裝依賴
首先,需要安裝Session中間件:
go get github.com/gin-contrib/sessions
2. 創(chuàng)建基于內(nèi)存的Session
Session存儲引擎有多種實現(xiàn)方式,如基于內(nèi)存、Redis、MongoDB等。以下是一個基于內(nèi)存的示例:
package main import ( "github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions/memstore" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() // 創(chuàng)建基于內(nèi)存的存儲引擎 // func NewStore(keyPairs ...[]byte) Store store := memstore.NewStore([]byte("secret11111")) // 設(shè)置Session中間件 // func Sessions(name string, store Store) gin.HandlerFunc r.Use(sessions.Sessions("mysession", store)) r.GET("/", func(c *gin.Context) { // 初始化Session對象 session := sessions.Default(c) // 設(shè)置Session數(shù)據(jù) session.Set("username", "zhangsan") // 保存Session數(shù)據(jù) session.Save() c.JSON(200, gin.H{"message": "Session設(shè)置成功"}) }) r.GET("/get", func(c *gin.Context) { // 初始化Session對象 session := sessions.Default(c) // 獲取Session數(shù)據(jù) username := session.Get("username") c.JSON(200, gin.H{"username": username}) }) r.Run(":8080") }
在上面的代碼中,memstore.NewStore([]byte(“secret11111”))創(chuàng)建了一個基于內(nèi)存的Session存儲引擎,sessions.Sessions(“mysession”, store)設(shè)置了Session中間件,其中"mysession"是Session的名稱,也是Cookie的名稱。
當(dāng)我們訪問首頁,設(shè)置session成功
當(dāng)我們訪問/get,可以獲取session
在控制器中使用Session
在Gin框架的控制器中,可以使用sessions.Default©方法獲取當(dāng)前的Session對象,然后調(diào)用Set、Get和Save等方法來設(shè)置、獲取和保存Session數(shù)據(jù)。
3. 創(chuàng)建基于Redis存儲Session
如果希望將Session數(shù)據(jù)保存在Redis中,可以使用github.com/gin-contrib/sessions/redis包。以下是一個示例:
首先,安裝Redis存儲引擎的包:
go get -u github.com/gin-contrib/sessions/redis
然后,配置Redis存儲引擎:
package main import ( "github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions/redis" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() // 創(chuàng)建基于Redis的存儲引擎 // func NewStore(size int, network, address, password string, keyPairs ...[]byte) (Store, error) // func NewStoreWithDB(size int, network, address, password, DB string, keyPairs ...[]byte) (Store, error) 指定DB store, _ := redis.NewStoreWithDB(10, "tcp", "10.10.0.100:6379", "123456", "0", []byte("secret")) // 設(shè)置Session中間件 r.Use(sessions.Sessions("mysession", store)) r.GET("/", func(c *gin.Context) { // 初始化Session對象 session := sessions.Default(c) // 設(shè)置Session數(shù)據(jù) session.Set("username", "jingtian") // 保存Session數(shù)據(jù) session.Save() c.JSON(200, gin.H{"message": "Session設(shè)置成功"}) }) r.GET("/get", func(c *gin.Context) { // 初始化Session對象 session := sessions.Default(c) // 獲取Session數(shù)據(jù) username := session.Get("username") c.JSON(200, gin.H{"username": username}) }) r.Run(":8080") }
瀏覽器訪問首頁,session保存成功
登錄redis查看,可以看到session
5. Session的基本操作
在獲取到Session對象后,我們可以對其進(jìn)行設(shè)置、獲取、刪除和清除等操作。需要注意的是,每次對Session進(jìn)行修改后,都需要調(diào)用session.Save()方法來保存更改。
設(shè)置Session:
session.Set("username", "zhangsan") session.Save()
獲取Session:
username := session.Get("username")
刪除Session中的某個鍵值對:
session.Delete("username") session.Save()
清除整個Session:
session.Clear() session.Save()
三、注意事項
- Cookie的Secure屬性:當(dāng)設(shè)置為
true
時,Cookie僅在HTTPS中有效。在生產(chǎn)環(huán)境中,為了安全起見,建議啟用HTTPS并設(shè)置Secure屬性。 - Cookie的HttpOnly屬性:設(shè)置為
true
時,可以防止通過JS腳本讀取Cookie,增加安全性。 - Session的過期時間:可以通過設(shè)置Session存儲引擎的Options來配置過期時間等參數(shù)。
- 跨域問題:在涉及跨域請求時,需要確保服務(wù)器正確配置了CORS(跨域資源共享)中間件,并允許攜帶Credentials。
- Gob編解碼器:Gin框架的Session中間件使用Gob作為編解碼器。當(dāng)存儲復(fù)雜類型(如struct、map等)時,需要先注冊這些類型,否則會報錯“gob: type not registered for…”。
四、總結(jié)
本文詳細(xì)介紹了在Go語言的Gin框架中如何使用Cookie和Session來實現(xiàn)跨請求的數(shù)據(jù)共享。通過合理配置和使用這些機(jī)制,我們可以有效地管理客戶端狀態(tài),提高應(yīng)用程序的可用性和安全性。
以上就是關(guān)于Gin框架中的Cookie和Session的使用方法的詳細(xì)內(nèi)容,更多關(guān)于Gin框架Cookie和Session的使用的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
一文帶你了解Golang中強(qiáng)大的重試機(jī)制
在 Go 語言中,處理瞬態(tài)錯誤是常見的挑戰(zhàn),這些錯誤可能會在一段時間后自動恢復(fù),因此,重試機(jī)制在這些情況下非常重要,所以本文就來和大家聊聊Golang中強(qiáng)大的重試機(jī)制吧2025-01-01go?tool?pprof?參數(shù)?'-base'?和?'-diff_base&
這篇文章主要介紹了go?tool?pprof?參數(shù)?'-base'?和?'-diff_base'之間的區(qū)別,兩個參數(shù)都是用于計算當(dāng)前?profile文件減去基準(zhǔn)profile文件所獲得的差值,用這個差值生成一個新的profile文件,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-05-05