GO-會話控制

第 7 章:會話控制

HTTP 是無狀態協議,伺服器不能記錄瀏覽器的訪問狀態,也就是說伺服器不能區分中兩次請求是否由一個客戶端發出。這樣的設計嚴重阻礙的 Web 程式的設計。如:在我們進行網購時,買了一條褲子,又買了一個手機。由於 http 協議是無狀態的,如果不通過其他手段,伺服器是不能知道用戶到底買了什麼。而 Cookie 就是解決方案之一。

7.1.1 簡介

Cookie 實際上就是伺服器保存在瀏覽器上的一段資訊。瀏覽器有了 Cookie 之後,每次向伺服器發送請求時都會同時將該資訊發送給伺服器,伺服器收到請求後,就可以根據該資訊處理請求。

  1. 第一次向伺服器發送請求時在伺服器端創建 Cookie
  2. 將在伺服器端創建的 Cookie 以響應頭的方式發送給瀏覽器
  3. 以後再發送請求瀏覽器就會攜帶著該 Cookie
  4. 伺服器得到 Cookie 之後根據 Cookie 的資訊來區分不同的用戶
  1. 在伺服器創建 Cookie 並將它發送給瀏覽器
  • 伺服器端程式碼
func handler(w http.ResponseWriter, r * http.Request) {  	cookie1: = http.Cookie {  		Name: "user1",  		Value: "admin",  		HttpOnly: true,  	}  	cookie2: = http.Cookie {  		Name: "user2",  		Value: "superAdmin",  		HttpOnly: true,  	}  	//將 Cookie 發送給瀏覽器,即添加第一個 Cookie  	w.Header().Set("Set-Cookie", cookie1.String())  	//再添加一個 Cookie  	w.Header().Add("Set-Cookie", cookie2.String())  }
  • 瀏覽器響應報文中的內容
HTTP/1.1 200 OK  Set-Cookie: user1=admin; HttpOnly  Set-Cookie: user2=superAdmin; HttpOnly  Date: Sun, 12 Aug 2018 07:24:49 GMT  Content-Length: 0  Content-Type: text/plain; charset=utf-8
  1. 以後每次發送請求瀏覽器都會攜帶著 Cookie
GET /cookie HTTP/1.1  Host: localhost:8080  Connection: keep-alive  Upgrade-Insecure-Requests: 1  User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)  AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62  Safari/537.36  Accept:  text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/  apng,*/*;q=0.8  Accept-Encoding: gzip, deflate, br  Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7  Cookie: user1=admin; user2=superAdmin
  1. 除了 Set 和 Add 方法之外,Go 還提供了一種更快捷的設置 Cookie 的方式,就是通過 net/http 庫中的 SetCookie 方法
  • 將 1)中的程式碼進行修改
func handler(w http.ResponseWriter, r * http.Request) {  	cookie1: = http.Cookie {  		Name: "user1",  		Value: "admin",  		HttpOnly: true,  	}  	cookie2: = http.Cookie {  		Name: "user2",  		Value: "superAdmin",  		HttpOnly: true,  	}  	http.SetCookie(w, & cookie1)  	http.SetCookie(w, & cookie2)  }

由於我們在發送請求時 Cookie 在請求頭中,所以我們可以通過 Request 結構中的Header 欄位來獲取 Cookie

  1. 處理器端程式碼
func handler(w http.ResponseWriter, r * http.Request) {  	//獲取請求頭中的 Cookie  	cookies: = r.Header["Cookie"]  	fmt.Fprintln(w, cookies)  }
  1. 瀏覽器中的結果
[user1=admin; user2=superAdmin]

Cookie默認是會話級別的,當關閉瀏覽器之後Cookie將失效,我們可以通過Cookie結構的 MaxAge 欄位設置 Cookie 的有效時間

  1. 處理器端程式碼
func handler(w http.ResponseWriter, r * http.Request) {  	cookie: = http.Cookie {  		Name: "user",  		Value: "persistAdmin",  		HttpOnly: true,  		MaxAge: 60,  	}  	//將 Cookie 發送給瀏覽器  	w.Header().Set("Set-Cookie", cookie.String())  }
  1. 瀏覽器響應報文中的內容
HTTP/1.1 200 OK  Set-Cookie: user=persistAdmin; Max-Age=60; HttpOnly  Date: Sun, 12 Aug 2018 07:32:57 GMT  Content-Length: 0  Content-Type: text/plain; charset=utf-8
  1. 廣告推薦
  2. 免登錄

7.2 Session

7.2.1 簡介

使用 Cookie 有一個非常大的局限,就是如果 Cookie 很多,則無形的增加了客戶端與服務端的數據傳輸量。而且由於瀏覽器對 Cookie 數量的限制,註定我們不能再Cookie 中保存過多的資訊,於是 Session 出現。

Session 的作用就是在伺服器端保存一些用戶的數據,然後傳遞給用戶一個特殊的 Cookie,這個 Cookie 對應著這個伺服器中的一個 Session,通過它就可以獲取到保存用戶資訊的 Session,進而就知道是那個用戶再發送請求。

7.2.2 Session 的運行原理

  1. 第一次向伺服器發送請求時創建 Session,給它設置一個全球唯一的 ID(可以通過UUID 生成)
  2. 創建一個 Cookie,將 Cookie 的 Value 設置為 Session 的 ID 值,並將 Cookie 發送給瀏覽器
  3. 以後再發送請求瀏覽器就會攜帶著該 Cookie
  4. 伺服器獲取 Cookie 並根據它的 Value 值找到伺服器中對應的 Session,也就知道了請求是那個用戶發的