Cookie和Session是Web開發繞不開的一個環節,本文介紹了Cookie和Session的原理及在Go語言中如何操作Cookie,
Cookie
Cookie的由來
HTTP協議是無狀態的,這就存在一個問題,
無狀態的意思是每次請求都是獨立的,它的執行情況和結果與前面的請求和之后的請求都無直接關系,它不會受前面的請求回應情況直接影響,也不會直接影響后面的請求回應情況,
一句有意思的話來描述就是人生只如初見,對服務器來說,每次的請求都是全新的,
狀態可以理解為客戶端和服務器在某次會話中產生的資料,那無狀態的就以為這些資料不會被保留,會話中產生的資料又是我們需要保存的,也就是說要“保持狀態”,因此Cookie就是在這樣一個場景下誕生,
Cookie是什么
在 Internet 中,Cookie 實際上是指小量資訊,是由 Web 服務器創建的,將資訊存盤在用戶計算機上(客戶端)的資料檔案,一般網路用戶習慣用其復數形式 Cookies,指某些網站為了辨別用戶身份、進行 Session 跟蹤而存盤在用戶本地終端上的資料,而這些資料通常會經過加密處理,
Cookie的機制
Cookie是由服務器端生成,發送給User-Agent(一般是瀏覽器),瀏覽器會將Cookie的key/value保存到某個目錄下的文本檔案內,下次請求同一網站時就發送該Cookie給服務器(前提是瀏覽器設定為啟用cookie),Cookie名稱和值可以由服務器端開發自己定義,這樣服務器可以知道該用戶是否是合法用戶以及是否需要重新登錄等,服務器可以設定或讀取Cookies中包含資訊,借此維護用戶跟服務器會話中的狀態,
總結一下Cookie的特點:
- 瀏覽器發送請求的時候,自動把攜帶該站點之前存盤的Cookie資訊,
- 服務端可以設定Cookie資料,
- Cookie是針對單個域名的,不同域名之間的Cookie是獨立的,
- Cookie資料可以配置過期時間,過期的Cookie資料會被系統清除,
查看Cookie
我們使用Chrome瀏覽器打開一個網站,打開開發者工具查看該網站保存在我們電腦上的Cookie資料,
Go操作Cookie
Cookie
標準庫net/http中定義了Cookie,它代表一個出現在HTTP回應頭中Set-Cookie的值里或者HTTP請求頭中Cookie的值的HTTP cookie,
type Cookie struct {
Name string
Value string
Path string
Domain string
Expires time.Time
RawExpires string
// MaxAge=0表示未設定Max-Age屬性
// MaxAge<0表示立刻洗掉該cookie,等價于"Max-Age: 0"
// MaxAge>0表示存在Max-Age屬性,單位是秒
MaxAge int
Secure bool
HttpOnly bool
Raw string
Unparsed []string // 未決議的“屬性-值”對的原始文本
}
設定Cookie
net/http中提供了如下SetCookie函式,它在w的頭域中添加Set-Cookie頭,該HTTP頭的值為cookie,
func SetCookie(w ResponseWriter, cookie *Cookie)
獲取Cookie
Request物件擁有兩個獲取Cookie的方法和一個添加Cookie的方法:
獲取Cookie的兩種方法:
// 決議并回傳該請求的Cookie頭設定的所有cookie func (r *Request) Cookies() []*Cookie // 回傳請求中名為name的cookie,如果未找到該cookie會回傳nil, ErrNoCookie, func (r *Request) Cookie(name string) (*Cookie, error)
添加Cookie的方法:
// AddCookie向請求中添加一個cookie, func (r *Request) AddCookie(c *Cookie)
gin框架操作Cookie
import (
"fmt"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
router.GET("/cookie", func(c *gin.Context) {
cookie, err := c.Cookie("gin_cookie") // 獲取Cookie
if err != nil {
cookie = "NotSet"
// 設定Cookie
c.SetCookie("gin_cookie", "test", 3600, "/", "localhost", false, true)
}
fmt.Printf("Cookie value: %s \n", cookie)
})
router.Run()
}
Session
Session的由來
Cookie雖然在一定程度上解決了“保持狀態”的需求,但是由于Cookie本身最大支持4096位元組,以及Cookie本身保存在客戶端,可能被攔截或竊取,因此就需要有一種新的東西,它能支持更多的位元組,并且他保存在服務器,有較高的安全性,這就是Session,
問題來了,基于HTTP協議的無狀態特征,服務器根本就不知道訪問者是“誰”,那么上述的Cookie就起到橋接的作用,
用戶登陸成功之后,我們在服務端為每個用戶創建一個特定的session和一個唯一的標識,它們一一對應,其中:
- Session是在服務端保存的一個資料結構,用來跟蹤用戶的狀態,這個資料可以保存在集群、資料庫、檔案中;
- 唯一標識通常稱為
Session ID會寫入用戶的Cookie中,
這樣該用戶后續再次訪問時,請求會自動攜帶Cookie資料(其中包含了Session ID),服務器通過該Session ID就能找到與之對應的Session資料,也就知道來的人是“誰”,
總結而言:Cookie彌補了HTTP無狀態的不足,讓服務器知道來的人是“誰”;但是Cookie以文本的形式保存在本地,自身安全性較差;所以我們就通過Cookie識別不同的用戶,對應的在服務端為每個用戶保存一個Session資料,該Session資料中能夠保存具體的用戶資料資訊,
另外,上述所說的Cookie和Session其實是共通性的東西,不限于語言和框架,
練習題
- 撰寫代碼實作一個gin框架版Session中間件,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/45048.html
標籤:Go
上一篇:Go pprof性能調優
