完全弄懂session,cookie,token

session,cookie和token到底是什麼

簡述

我在寫以前看了不少篇session,cookie的文章,有的人說先有了cookie,後有了session。也有人說先有session,後有cookie。感受都沒有講的很清楚,泛泛而談。但願本篇文章對你們有所幫助
注:本文須要讀者有cookie,session,token的相關基礎知識。php

http是一個無狀態協議

什麼是無狀態呢?就是說這一次請求和上一次請求是沒有任何關係的,互不認識的,沒有關聯的。這種無狀態的的好處是快速。壞處是假如咱們想要把www.zhihu.com/login.htmlwww.zhihu.com/index.html關聯起來,必須使用某些手段和工具html

cookie和session

因爲http的無狀態性,爲了使某個域名下的全部網頁可以共享某些數據,session和cookie出現了。客戶端訪問服務器的流程以下web

  • 首先,客戶端會發送一個http請求到服務器端。
  • 服務器端接受客戶端請求後,創建一個session,併發送一個http響應到客戶端,這個響應頭,其中就包含Set-Cookie頭部。該頭部包含了sessionId。Set-Cookie格式以下,具體請看Cookie詳解
    Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]
  • 在客戶端發起的第二次請求,假如服務器給了set-Cookie,瀏覽器會自動在請求頭中添加cookie
  • 服務器接收請求,分解cookie,驗證信息,覈對成功後返回response給客戶端

請求流程

注意

  • cookie只是實現session的其中一種方案。雖然是最經常使用的,但並非惟一的方法。禁用cookie後還有其餘方法存儲,好比放在url中
  • 如今大多都是Session + Cookie,可是隻用session不用cookie,或是隻用cookie,不用session在理論上均可以保持會話狀態。但是實際中由於多種緣由,通常不會單獨使用
  • 用session只須要在客戶端保存一個id,實際上大量數據都是保存在服務端。若是所有用cookie,數據量大的時候客戶端是沒有那麼多空間的。
  • 若是隻用cookie不用session,那麼帳戶信息所有保存在客戶端,一旦被劫持,所有信息都會泄露。而且客戶端數據量變大,網絡傳輸的數據量也會變大

小結

簡而言之, session 有如用戶信息檔案表, 裏面包含了用戶的認證信息和登陸狀態等信息. 而 cookie 就是用戶通行證數據庫

token

token 也稱做令牌,由uid+time+sign[+固定參數]
token 的認證方式相似於臨時的證書籤名, 而且是一種服務端無狀態的認證方式, 很是適合於 REST API 的場景. 所謂無狀態就是服務端並不會保存身份認證相關的數據。json

組成

  • uid: 用戶惟一身份標識
  • time: 當前時間的時間戳
  • sign: 簽名, 使用 hash/encrypt 壓縮成定長的十六進制字符串,以防止第三方惡意拼接
  • 固定參數(可選): 將一些經常使用的固定參數加入到 token 中是爲了不重複查庫

存放

token在客戶端通常存放於localStorage,cookie,或sessionStorage中。在服務器通常存於數據庫中segmentfault

token認證流程

token 的認證流程與cookie很類似api

  • 用戶登陸,成功後服務器返回Token給客戶端。
  • 客戶端收到數據後保存在客戶端
  • 客戶端再次訪問服務器,將token放入headers中
  • 服務器端採用filter過濾器校驗。校驗成功則返回請求數據,校驗失敗則返回錯誤碼

token能夠抵抗csrf,cookie+session不行

假如用戶正在登錄銀行網頁,同時登錄了攻擊者的網頁,而且銀行網頁未對csrf攻擊進行防禦。攻擊者就能夠在網頁放一個表單,該表單提交src爲http://www.bank.com/api/transfer,body爲count=1000&to=Tom。假若是session+cookie,用戶打開網頁的時候就已經轉給Tom1000元了.由於form 發起的 POST 請求並不受到瀏覽器同源策略的限制,所以能夠任意地使用其餘域的 Cookie 向其餘域發送 POST 請求,造成 CSRF 攻擊。在post請求的瞬間,cookie會被瀏覽器自動添加到請求頭中。但token不一樣,token是開發者爲了防範csrf而特別設計的令牌,瀏覽器不會自動添加到headers裏,攻擊者也沒法訪問用戶的token,因此提交的表單沒法經過服務器過濾,也就沒法造成攻擊。跨域

分佈式狀況下的session和token

咱們已經知道session時有狀態的,通常存於服務器內存或硬盤中,當服務器採用分佈式或集羣時,session就會面對負載均衡問題。瀏覽器

  • 負載均衡多服務器的狀況,很差確認當前用戶是否登陸,由於多服務器不共享session。這個問題也能夠將session存在一個服務器中來解決,可是就不能徹底達到負載均衡的效果。當今的幾種解決session負載均衡的方法。

而token是無狀態的,token字符串裏就保存了全部的用戶信息服務器

  • 客戶端登錄傳遞信息給服務端,服務端收到後把用戶信息加密(token)傳給客戶端,客戶端將token存放於localStroage等容器中。客戶端每次訪問都傳遞token,服務端解密token,就知道這個用戶是誰了。經過cpu加解密,服務端就不須要存儲session佔用存儲空間,就很好的解決負載均衡多服務器的問題了。這個方法叫作JWT(Json Web Token)

總結

  • session存儲於服務器,能夠理解爲一個狀態列表,擁有一個惟一識別符號sessionId,一般存放於cookie中。服務器收到cookie後解析出sessionId,再去session列表中查找,才能找到相應session。依賴cookie
  • cookie相似一個令牌,裝有sessionId,存儲在客戶端,瀏覽器一般會自動添加。
  • token也相似一個令牌,無狀態,用戶信息都被加密到token中,服務器收到token後解密就可知道是哪一個用戶。須要開發者手動添加。
  • jwt只是一個跨域認證的方案

參考文章

Cookie、Session、Token那點事兒
cookie,token驗證的區別
有了cookie爲何須要session
CSRF Token的設計是否有其必要性
cookie,token,session三者的問題和解決方案
負載均衡集羣中的session解決方案
JWT介紹
Json Web Token 入門教程

謝謝

本文若有錯誤,歡迎留言討論

相關文章
相關標籤/搜索