大話javascript 7期:Cookie、Session和Token的那些事兒

1、登陸認證機制

隨着互聯網的不斷髮展,不管是網站仍是app,通常都會要求用戶註冊/登陸。主要的登陸方式有帳戶密碼登陸、第三方登陸(微信登陸、QQ登陸、微博登陸等)

登陸可分爲三個階段(登陸驗證、登陸持續、退出登陸);
登陸驗證指客戶端提供帳號/密碼(或第三方平臺(微信、qq)獲取openid/unionid)向服務器提出登陸請求,服務器應答請求判斷可否登陸並返回相應數據;
登陸持續指客戶端登陸後, 服務器可以分辨出已登陸的客戶端,併爲其持續提供登陸權限的服務器。
退出登陸指客戶端退出登陸狀態。前端

2、保持登陸持續狀態的實現方式

爲何要保持登陸狀態的持續?

因爲HTTP是一種無狀態的協議,服務器單從網絡鏈接上無從知道客戶身份。怎麼辦呢?就給客戶端們頒發一個通行證吧,每人一個,不管誰訪問都必須攜帶本身通行證web

方案:客戶端登陸成功後, 服務器爲其分配一個惟一的憑證, 客戶端每次請求資源時都帶上這個憑證;

實現方案面試

  1. cookie 會話機制
  2. session 會話機制
  3. token 會話機制

3、Cookie、Session和Token

Cookie(瀏覽器緩存)

1.什麼是Cookie

Cookie其實是一小段的文本信息。客戶端請求服務器,若是服務器須要記錄該用戶狀態,就使用response向客戶端瀏覽器頒發一個Cookie。客戶端瀏覽器會把Cookie保存起來。當瀏覽器再請求該網站時,瀏覽器把請求的網址連同該Cookie一同提交給服務器。服務器檢查該Cookie,以此來辨認用戶狀態。服務器還能夠根據須要修改Cookie的內容。redis

clipboard.png

cookie實際上是補充http協議的無狀態性的缺點,底層是經過服務器端在http響應消息中增長set-cookie字段來將cookie信息發送給瀏覽器端,由於它只能存4k,通常用來存瀏覽器的身份信息,瀏覽器在訪問服務器的某些資源的時候,會在http請求頭中將cookie數據傳給服務器,這樣服務器就知道是誰請求的了,可是若是用戶清除了cookie,那就啥都沒有了算法

2.Cookie的屬性

clipboard.png

clipboard.png

一、Expires:該Cookie失效的時間,單位秒。數據庫

  • 若是爲正數,則該Cookie在maxAge秒以後失效(持久級別Cookie)。
  • 若是爲負數,該Cookie爲臨時Cookie,關閉瀏覽器即失效(會話級別Cookie),瀏覽器也不會以任何形式保存該Cookie。
  • 若是爲0,表示刪除該Cookie。默認爲–1;

二、Domain:
咱們如今有二個域名。域名A:b.f.com,域名B:d.f.com;顯然域名A和域名B都是f.com的子域名後端

  • 若是咱們在域名A中的Cookie的domain設置爲.f.com,那麼.f.com及其子域名均可以獲取這個Cookie,即域名A和域名B均可以獲取這個Cookie
  • 若是域名A沒有顯式設置Cookie的domain方法,那麼domain就爲.b.f.com,不同的是,這時,域名A的子域名將沒法獲取這個Cookie
  • HttpOnly: 這個屬性是面試的時候常考的,若是這個屬性設置爲true,就不能經過js腳原本獲取cookie的值,能有效的防止xss攻擊

3.Cookie的操做

封裝cookie的經常使用操做方法瀏覽器

  • 設置cookie
  • 讀取cookie
  • 刪除cookie
var cookieUtil = {
    getItem: function (name) {
        var cookieName = encodeURIComponent(name) + "=",
            cookieStart = document.cookie.indexOf(cookieName),
            cookieValue = null;
        if (cookieStart > -1) {
            var cookieEnd = document.cookie.indexOf(';', cookieStart);
            if (cookieEnd == 1) {
                cookieEnd = document.cookie.length;
            }
            cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd))
        }
        return cookieValue;
    },
    setItem: function (name, value, expires, path, domain, secure) {
        var cookieText = encodeURIComponent(name) + "=" + encodeURIComponent(value);
        if (expires) {
            cookieText += ";expires=" + expires.toGMTString();
        }
        if (path) {
            cookieText += ";path=" + path;
        }
        if (domain) {
            cookieText += ";domain=" + domain;
        }
        if (secure) {
            cookieText += ";secure";
        }
        document.cookie = cookieText;
    },
    unset: function (name, path, domain, secure) {
        this.setItem(name, "", new Date(0), path, domain, secure)
    }
}
CookieUtil.setItem("name", 'tom'); // 設置cookie
console.log(CookieUtil.getItem('name'));//讀取cookie
CookieUtil.unset("name")//刪除cookie

4.Cookie防篡改機制

由於Cookie是存儲在客戶端,用戶能夠隨意修改。因此,存在必定的安全隱患。
防篡改簽名:服務器爲每一個Cookie項生成簽名。若是用戶篡改Cookie,則與簽名沒法對應上。以此,來判斷數據是否被篡改。

原理以下:緩存

  • 服務端提供一個簽名生成算法secret
  • 根據方法生成簽名secret(wall)=34Yult8i
  • 將生成的簽名放入對應的Cookie項username=wall|34Yult8i。其中,內容和簽名用|隔開。
  • 服務端根據接收到的內容和簽名,校驗內容是否被篡改。

舉個栗子:
好比服務器接收到請求中的Cookie項username=pony|34Yult8i,而後使用簽名生成算法secret(pony)=666。 算法獲得的簽名666和請求中數據的簽名不一致,則證實數據被篡改。安全

Session(會話)

1.什麼是session

session是一種服務器機制,是存儲在服務器上的信息,主要配合cookie完成瀏覽器的身份認證和狀態存儲方式多種多樣,能夠是服務器的內存中,或者是mongo數據庫,redis內存數據庫中。爲了得到更高的存取速度,服務器通常把Session放在內存裏。每一個用戶都會有一個獨立的Session。若是Session內容過於複雜,當大量客戶訪問服務器時可能會致使內存溢出。所以,Session裏的信息應該儘可能精簡。

Session相對於cookie較安全點,當用戶請求服務器的時候,服務器會把數據臨時存下來,若是退出網站後,session會被銷燬。

Session是基於cookie實現的,瀏覽器第一次訪問服務器時,服務器建立一個Session,同時生成一個惟一的會話key,即sessionID。接着sessionIDsession分別做爲keyvalue保存到緩存中,也能夠保存到數據庫中,而後服務器把sessionID經過set-cookie的方式寫入瀏覽器,瀏覽器下次訪問服務器時直接攜帶上cookie中的sessionID,服務器再根據sessionID找到對應的session進行匹配,來判斷用戶是否登陸

2.session鑑權過程

【1】 客戶端發起登陸請求,服務器端建立session,並經過set-cookie將生成的sessionID寫入的客戶端的cookie中。
【2】 在發起其餘須要權限的接口的時候,客戶端的請求體的Header部分會攜帶sessionID發送給服務端。而後根據這個sessionId去找服務器端保存的該客戶端的session,而後判斷該請求是否合法。

3.cookie和session的區別

clipboard.png

Token(身份令牌)

1.什麼是token

token的意思是「令牌」,是用戶身份的驗證方式,最簡單的token組成:uid(用戶惟一的身份標識)、time(當前時間的時間戳)、sign(簽名,由token的前幾位+鹽以哈希算法壓縮成必定長的十六進制字符串,能夠防止惡意第三方拼接token請求服務器)。還能夠把不變的參數也放進token,避免屢次查庫

瀏覽器第一次訪問服務器,根據傳過來的惟一標識userId,服務端會經過一些算法,如經常使用的HMAC-SHA256算法,而後加一個密鑰,生成一個token,而後經過BASE64編碼一下以後將這個token發送給客戶端;客戶端將token保存起來,下次請求時,帶着token,服務器收到請求後,而後會用相同的算法和密鑰去驗證token,若是經過,執行業務操做,不經過,返回不經過信息;

2.token生成方式

瀏覽器第一次訪問服務器時,服務器根據傳過來的惟一標識userId,經過一些算法,加一個密鑰,生成一個token,接着經過base64編碼將token返回給客戶端。客戶端將token保存起來,下次請求時須要帶着token,服務器收到請求後,用相同的算法和密鑰去驗證token

3.token和session的區別

token和session其實都是爲了身份驗證,session通常翻譯爲會話,而token更多的時候是翻譯爲令牌;
session服務器會保存一份,可能保存到緩存,文件,數據庫;一樣,session和token都是有過時時間一說,都須要去管理過時時間;
其實token與session的問題是一種時間與空間的博弈問題,session是空間換時間,而token是時間換空間。二者的選擇要看具體狀況而定。
雖然確實都是「客戶端記錄,每次訪問攜帶」,但 token 很容易設計爲自包含的,也就是說,後端不須要記錄什麼東西,每次一個無狀態請求,每次解密驗證,每次當場得出合法 /非法的結論。這一切判斷依據,除了固化在 CS 兩端的一些邏輯以外,整個信息是自包含的。這纔是真正的無狀態。
而 sessionid ,通常都是一段隨機字符串,須要到後端去檢索 id 的有效性。萬一服務器重啓致使內存裏的 session 沒了呢?萬一 redis 服務器掛了呢?

sessionID是基於cookie實現的,而token不須要基於cookie。這就致使了sessionID只能用在瀏覽器上,對於原生的應用沒法實現。原生的應用是不具有cookie的特性的。另外sessionID能夠實現服務端註銷會話,而token不能(固然你能夠把用戶登錄的token存入到redis中,可是不推薦token入庫)

4.token的優勢

Token做爲用戶認證的處理方式,有幾個優勢:

  • 無狀態,可擴展:不會在服務端存儲用戶的登陸狀態,能夠很容易的實現服務器的增減
  • 支持移動設備,對多類型客戶端的支持良好
  • 支持跨程序調用,各個接口之間的調用更方便
  • 安全可靠

5.什麼是JSON Web Token

JSON web Token,簡稱JWT,本質是一個token,是一種緊湊的URL安全方法,用於在網絡通訊的雙方之間傳遞。通常放在HTTP的headers參數裏面的authorization裏面,值的前面加Bearer關鍵字和空格。除此以外,也能夠在url和request body中傳遞。

Json web token (JWT), 是爲了在網絡應用環境間傳遞聲明而執行的一種基於JSON的開放標準((RFC 7519).該token被設計爲緊湊且安全的,特別適用於分佈式站點的單點登陸(SSO)場景。JWT的聲明通常被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便於從資源服務器獲取資源,也能夠增長一些額外的其它業務邏輯所必須的聲明信息,該token也可直接被用於認證,也可被加密。

若是你以爲這篇文章對你有所幫助,那就順便點個贊吧,點點關注不迷路~

黑芝麻哇,白芝麻發,黑芝麻白芝麻哇發哈!

前端哇發哈

相關文章
相關標籤/搜索