## HTTP
郵件服務器必須得管理會話,因為如果不管理的話,多個人的郵件就混到一起去了。
但是很早之前的Web基本上就是文檔的瀏覽而已,服務器根本不需要記住誰在一段時間里瀏覽了什么文檔。
## Session
后來大家不滿足靜態的HTML文檔了,交互式的Web開始興起。
此時Web服務器必須管理會話,必須知道哪些人登錄了系統,哪些人往自己的購物車里面放了東西。
由于HTTP協議的無狀態特性,必須曲線救國
可以給每個人發一個會話標識session id,也就是一個隨機字符串,當瀏覽器發起HTTP請求的時候,會把這個session id一起帶過來,就可以區分誰是誰了。
## 沉重的負擔
使用session id的壞處在于,服務器需要保存所有人的session id。
這是巨大的開銷,嚴重限制了擴展能力,比如說兩個機器組成了集群,一個人通過機器A登錄了系統,那么session id會保存在機器A上,但是如果下一次請求發到了機器B怎么辦?
于是可以使用session sticky。也就是說這個人的請求一直都只轉發到機器A上。
那么機器A如果掛了怎么辦?
只要做session 復制了,這樣又涉及到session id在兩個機器之間搬來搬去

后來Memcached將session id放到一個地方,所有機器都來訪問這個地方的數據。
但是又增加了單點失敗的可能性。

如果不存儲session id的機器又搞出個集群,感覺對一個小小的session 還殺雞用牛刀
## 時間換空間
那么Web服務器可以不保存session嗎?
但是如果不保存session,如何驗證客戶端發過來的session id是服務器生成的,而非偽造的呢?
所以關鍵點在于驗證。
比如說一個人登錄了系統,就可以給他發一個token,這個token需要包含這個人的user id 。
下次這個人再訪問服務器的時候,可以把這個token順道帶過來。
但是依然沒有解決易被偽造的問題。
那么就可以對數據做一個簽名,比如使用HMAC-SHA256算法,加上一個不公開的密鑰,可以對數據做簽名。
這個簽名與數據放在一起做為token
只要保管好了token,別人就無法偽造。

所以服務器不需要保存token,當人們把 token發過來的時候,可以使用SHA256算法+密鑰,再對數據重新計算一次,并與token 中的簽名做比較。
如果相同,則說明一定登錄過了。

Token 中的數據是明文保存的,所以不能在其中保存像密碼那樣的敏感信息
如果token被偷走了,也沒有辦法,這和一個人的session id被偷走了一樣。
總之,服務器是使用CPU計算時間來獲取了session 的存儲空間。
這樣,機器集群可以輕松做水平擴展,用戶量增大,直接加機器即可。