在web中,咱們常常說session,token,cookie。這三個內容,究竟啥區別,爲何會有這三個內容呢?這就是咱們今天想要討論的。ios
洋洋: 琪琪,大家原先的開發 權限是怎麼認證的?web
琪琪: 權限?不就是攔截器嘛?經過攔截不一樣的url,進行攔截,而後進行校驗。redis
洋洋: 那大家用過shiro嘛?進行權限校驗的。算法
琪琪: 那個卻是沒用過,我原先了解是用token作的,而後再造輪子寫權限。sql
洋洋: 哦哦那你講下session與token 是啥?我仍是有點不明白呢,大家當初是怎麼設計的?數據庫
既然要說 session 與token,順便了解下cookie?後端
co哥: 該我出場提問了。第一個問題: 爲何要有cookie? 琪琪: 爲何要有呢?(小樣,居然問我這麼簡單的問題)。有它不就是爲了存儲web中的狀態信息嘛,方便服務端使用嘛。瀏覽器
co哥:那cookie 通常是怎麼擁有的?客戶端能夠建立嘛? 琪琪:咱們都說cookie存在於客戶端,若是不是篡改的問題,cookie第一次是服務器向客戶端發送的。安全
co哥:你說的對,順便再加一個就是咱們的瀏覽器也會將cookie保存,而且每次請求後也把這些信息發送給服務端哦。bash
琪琪: 恩?那發送的是什麼格式呢?(自問自答怎麼樣?)有什麼限制嗎?
琪琪: cookie嗎? 簡單說就是遵循name=value 格式的字符串。還有就是4kB的大小限制,cookie中其餘內容就是可選項了。
琪琪: 還有一點就是set-cookie是在header中哦.
順便提供下主要構成嗎,你們能夠看下。
name:一個惟一肯定的cookie名稱。一般來說cookie的名稱是不區分大小寫的。
value:存儲在cookie中的字符串值。最好爲cookie的name和value進行url編碼
domain:cookie對於哪一個域是有效的。全部向該域發送的請求中都會包含這個cookie信息。這個值能夠包含子域(如:yq.aliyun.com),也能夠不包含它(如:.aliyun.com,則對於aliyun.com的全部子域都有效).
path: 表示這個cookie影響到的路徑,瀏覽器跟會根據這項配置,像指定域中匹配的路徑發送cookie。
expires:失效時間,表示cookie什麼時候應該被刪除的時間戳(也就是,什麼時候應該中止向服務器發送這個cookie)。若是不設置這個時間戳,瀏覽器會在頁面關閉時即將刪除全部cookie;不過也能夠本身設置刪除時間。這個值是GMT時間格式,若是客戶端和服務器端時間不一致,使用expires就會存在誤差。
max-age: 與expires做用相同,用來告訴瀏覽器此cookie多久過時(單位是秒),而不是一個固定的時間點。正常狀況下,max-age的優先級高於expires。
HttpOnly: 告知瀏覽器不容許經過腳本document.cookie去更改這個值,一樣這個值在document.cookie中也不可見。但在http請求張仍然會攜帶這個cookie。注意這個值雖然在腳本中不可獲取,但仍然在瀏覽器安裝目錄中以文件形式存在。這項設置一般在服務器端設置。
secure: 安全標誌,指定後,只有在使用SSL連接時候才能發送到服務器,若是是http連接則不會傳遞該信息。就算設置了secure 屬性也並不表明他人不能看到你機器本地保存的 cookie 信息,因此不要把重要信息放cookie就對了
複製代碼
wa: 既然有了cookie,那爲何還出來session了?這是作什麼的?
瀏覽器第一次訪問服務器的時候,服務器會建立一個session,同時生成惟一的key,則是sessionID。
琪琪: 小黑板來了,我來提問了,第一次訪問,那多個瀏覽器使用同一個帳戶信息,服務器不作其餘限制,那是否是造成多個session呢?
wa: 固然了,每次訪問都會造成一個新的sessionID,那就是session不同了.這樣至關於session 都保持此次會話訪問的鏈接。
琪琪:會話訪問的鏈接?那就表明有狀態了哦。 那在後端是怎麼把session返回給客戶端的?
wa: 經過設置cookie的方式返回給客戶端哦。固然在後端的時候咱們也能夠將session保存到數據庫或者redis這些nosql中。
琪琪:咱們經過cookie發送了。但有時候瀏覽器禁止cookie怎麼辦?
wa: 這個嘛?我想一想...(你說你問這麼多幹嗎,還得費腦子)。能夠經過URL重寫的方式發送給服務器哦。
琪琪: 這也對。但還有個問題,若是咱們後臺有個服務器部署,屬於分佈式的,那我再其中一臺登陸了,稱爲A,session也保存到A中,萬一下次我訪問到另一臺服務器B怎麼辦?B上沒有A的session呢。
wa: enenen ? 你問我?我也不知道。
le: 來來,我說下吧。能夠這樣嘛,既然每一個服務器都有session,那咱們就保存到庫裏面算了。這樣咱們就能互相經過訪問過來的cookie 裏拿到session信息與庫中的進行對比。session 就共享了。
le: 嗯呢,因此集羣,出來了,因此每次保存這些session信息就是一個負擔了。這就是咱們須要在系統設計的時候考慮,狀態信息須要保存嘛?
session 是保存了會話的連接信息與咱們須要傳輸的內容,容量大,還須要保持會話信息,每次同一用戶不一樣客戶端訪問我都須要從新創建session,形成冗餘信息大。
ff: 這該怎麼辦呢,真不想保存。
琪琪:這還不簡單,那就不保存了,採用token吧?
ff: token? 那是個啥?
琪琪: ennnn,那不是啥。那是一個新技術,被稱爲令牌的東西。
ff: 那token能驗證用戶的合法性嘛?
琪琪: ...固然,好比用戶登陸了,咱們會把令牌信息,發送給他,包含了一個他的userId,表明他的信息,再訪問的時候經過header或者bady帶過來就好。
ff: 感受與sessionID沒有區別呢? 咦,貌似不用存儲session信息到庫裏面了,還有每次不一樣的會話建立新的token,也不影響(單點登陸貌似能夠經過token作哦,作過的小夥伴能夠嘗試下)。好神奇。
琪琪: 是的,是否是感受token比session好多了?
ff: ennnn,但這不是給黑客創造了僞造的 token信息嘛?怎麼防止這些信息呢?
琪琪: 這還不簡單,對我們返回的token裏面數據作一個簽名,祕鑰別人不知道,這樣僞造的token不就通不過咱們的限制了嘛。加密算法能夠採用HMAC-SHA256這些算法了etc.
ff :神奇的token啊。這就解決session 這些問題了。
嘿嘿,怎麼能結束呢,只說了理論,但還有不少問題沒解決呢。就讓琪琪一個個提問吧。
wa: 先不提問,我再說幾個結論,在提問。。
好了就先說這幾條吧,之後有了在補充。
琪琪:總結了這麼多了,那咱們開始提問了。首先,爲啥客戶端ios與Andriod基本上沒見過用session的?
ff: 這個我來回答吧。由於在這些客戶端上啊,原生接口都是每一次創建一個會話,這就出問題了,這樣會致使登陸功能失效了,登陸每次把信息放到session中,session都不同了,每次登陸都成新的一我的了,這就不ok了。
琪琪:哦哦原來客戶端是每次用原生接口都是新創建一個會話,好尷尬的設計。那咱們採用什麼方式解決這個問題呢?
ff: 在用戶登陸後,重點哦咱們能夠經過cookie嘛,咱們在app端也能夠是存儲cookie的,咱們知道cookie將sessionID保存好,返回給客戶端,服務器最後也是經過SessionId來標識的。可是利用token的話,內容咱們能夠自定義,而且不用再服務端進行保存。方便咱們處理。
琪琪:那麼就是token能夠保存到cookie中,若是禁止的話咱們也能夠保存到body中每次都請求上或者header中。
恩,token,cookie,session的內容就到這裏的,不一樣的方案都有各個的區別,固然從這裏看我門瞭解的仍是不不夠多,須要繼續努力
歡迎你們關注公衆號LuckQI.