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