Cookie和Session

更新、更全的《Go從入門到放棄》的更新網站,更有python、go、人工智能教學等着你:http://www.javashuo.com/article/p-mxrjjcnn-hn.htmlpython

Cookie和Session是Web開發繞不開的一個環節,本文介紹了Cookie和Session的原理及在Go語言中如何操做Cookie。git

1、Cookie

1.1 Cookie的由來

HTTP協議是無狀態的,這就存在一個問題。github

無狀態的意思是每次請求都是獨立的,它的執行狀況和結果與前面的請求和以後的請求都無直接關係,它不會受前面的請求響應狀況直接影響,也不會直接影響後面的請求響應狀況。數據庫

一句有意思的話來描述就是人生只如初見,對服務器來講,每次的請求都是全新的。瀏覽器

狀態能夠理解爲客戶端和服務器在某次會話中產生的數據,那無狀態的就覺得這些數據不會被保留。會話中產生的數據又是咱們須要保存的,也就是說要「保持狀態」。所以Cookie就是在這樣一個場景下誕生。安全

1.2 Cookie是什麼

在 Internet 中,Cookie 其實是指小量信息,是由 Web 服務器建立的,將信息存儲在用戶計算機上(客戶端)的數據文件。通常網絡用戶習慣用其複數形式 Cookies,指某些網站爲了辨別用戶身份、進行 Session 跟蹤而存儲在用戶本地終端上的數據,而這些數據一般會通過加密處理。服務器

1.3 Cookie的機制

Cookie是由服務器端生成,發送給User-Agent(通常是瀏覽器),瀏覽器會將Cookie的key/value保存到某個目錄下的文本文件內,下次請求同一網站時就發送該Cookie給服務器(前提是瀏覽器設置爲啓用cookie)。Cookie名稱和值能夠由服務器端開發本身定義,這樣服務器能夠知道該用戶是不是合法用戶以及是否須要從新登陸等,服務器能夠設置或讀取Cookies中包含信息,藉此維護用戶跟服務器會話中的狀態。cookie

總結一下Cookie的特色:網絡

  1. 瀏覽器發送請求的時候,自動把攜帶該站點以前存儲的Cookie信息。
  2. 服務端能夠設置Cookie數據。
  3. Cookie是針對單個域名的,不一樣域名之間的Cookie是獨立的。
  4. Cookie數據能夠配置過時時間,過時的Cookie數據會被系統清除。

1.4 查看Cookie

咱們使用Chrome瀏覽器打開一個網站,打開開發者工具查看該網站保存在咱們電腦上的Cookie數據。

2、Go操做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 // 未解析的「屬性-值」對的原始文本
}

2.2 設置Cookie

net/http中提供了以下SetCookie函數,它在w的頭域中添加Set-Cookie頭,該HTTP頭的值爲cookie。

func SetCookie(w ResponseWriter, cookie *Cookie)

2.3 獲取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)

3、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()
}

4、Session

4.1 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實際上是共通性的東西,不限於語言和框架。

5、練習題

  1. 編寫代碼實現一個gin框架版Session中間件。
相關文章
相關標籤/搜索