jwt無狀態存儲
Ⅰ jwt原理是什麼
GWT單點登錄原理這是一個技術原始問題,伺服器這邊准備一個密碼字元串,各伺服器保持字元串一樣。
當用戶登錄一台伺服器成功後,伺服器將他的賬號和密碼字元串通過演算法整合一下,形成一個新的字元串。通常這個演算法會將密碼字元串用哈希的方式來處理,但賬號可以直接在新的字元串中拿到。
這樣,伺服器將這個新的字元串給用戶(即保存在cookie中,或保存在storage中)。用戶每次訪問,都會帶上這個字元串(類似jsessionid)。伺服器這邊拿到用戶帶來的字元串,從中取出賬號,將賬號和伺服器這邊存。
字元串
在存儲上類似字元數組,它每一位單個元素都是能提取的,字元串的零位是它的長度,如s[0]=10,這提供給我們很多方便,例如高精度運算時每一位都能轉化為數字存入數組。
通常以串的整體作為操作對象,如:在串中查找某個子串、求取一個子串、在串的某個位置上插入一個子串以及刪除一個子串等。
兩個字元串相等的充要條件是:長度相等,並且各個對應位置上的字元都相等。設p、q是兩個串,求q在p中首次出現的位置的運算叫做模式匹配。串的兩種最基本的存儲方式是順序存儲方式和鏈接存儲方式。
Ⅱ 鑒權必須了解的 5 個兄弟:cookie、session、token、jwt、單點登錄
本文你將看到:
**「前端存儲」**這就涉及到一發、一存、一帶,發好辦,登陸介面直接返回給前端,存儲就需要前端想辦法了。
前端的存儲方式有很多。
有,cookie。cookie 也是前端存儲的一種,但相比於 localStorage 等其他方式,藉助 HTTP 頭、瀏覽器能力,cookie 可以做到前端無感知。一般過程是這樣的:
「配置:Domain / Path」
cookie 是要限制::「空間范圍」::的,通過 Domain(域)/ Path(路徑)兩級。
「配置:Expires / Max-Age」
cookie 還可以限制::「時間范圍」::,通過 Expires、Max-Age 中的一種。
「配置:Secure / HttpOnly」
cookie 可以限制::「使用方式」::。
**「HTTP 頭對 cookie 的讀寫」**回過頭來,HTTP 是如何寫入和傳遞 cookie 及其配置的呢?HTTP 返回的一個 Set-Cookie 頭用於向瀏覽器寫入「一條(且只能是一條)」cookie,格式為 cookie 鍵值 + 配置鍵值。例如:
那我想一次多 set 幾個 cookie 怎麼辦?多給幾個 Set-Cookie 頭(一次 HTTP 請求中允許重復)
HTTP 請求的 Cookie 頭用於瀏覽器把符合當前「空間、時間、使用方式」配置的所有 cookie 一並發給服務端。因為由瀏覽器做了篩選判斷,就不需要歸還配置內容了,只要發送鍵值就可以。
**「前端對 cookie 的讀寫」**前端可以自己創建 cookie,如果服務端創建的 cookie 沒加HttpOnly,那恭喜你也可以修改他給的 cookie。調用document.cookie可以創建、修改 cookie,和 HTTP 一樣,一次document.cookie能且只能操作一個 cookie。
調用document.cookie也可以讀到 cookie,也和 HTTP 一樣,能讀到所有的非HttpOnly cookie。
現在回想下,你刷卡的時候發生了什麼?
這種操作,在前後端鑒權系統中,叫 session。典型的 session 登陸/驗證流程:
**「Session 的存儲方式」**顯然,服務端只是給 cookie 一個 sessionId,而 session 的具體內容(可能包含用戶信息、session 狀態等),要自己存一下。存儲的方式有幾種:
「Session 的過期和銷毀」**很簡單,只要把存儲的 session 數據銷毀就可以。****「Session 的分布式問題」**通常服務端是集群,而用戶請求過來會走一次負載均衡,不一定打到哪台機器上。那一旦用戶後續介面請求到的機器和他登錄請求的機器不一致,或者登錄請求的機器宕機了,session 不就失效了嗎?這個問題現在有幾種解決方式。
但通常還是採用第一種方式,因為第二種相當於閹割了負載均衡,且仍沒有解決「用戶請求的機器宕機」的問題。**「node.js 下的 session 處理」**前面的圖很清楚了,服務端要實現對 cookie 和 session 的存取,實現起來要做的事還是很多的。在npm中,已經有封裝好的中間件,比如 express-session - npm,用法就不貼了。這是它種的 cookie:
express-session - npm 主要實現了:
session 的維護給服務端造成很大困擾,我們必須找地方存放它,又要考慮分布式的問題,甚至要單獨為了它啟用一套 Redis 集群。有沒有更好的辦法?
回過頭來想想,一個登錄場景,也不必往 session 存太多東西,那為什麼不直接打包到 cookie 中呢?這樣服務端不用存了,每次只要核驗 cookie 帶的「證件」有效性就可以了,也可以攜帶一些輕量的信息。這種方式通常被叫做 token。
token 的流程是這樣的:
**「客戶端 token 的存儲方式」 在前面 cookie 說過,cookie 並不是客戶端存儲憑證的唯一方式。token 因為它的「無狀態性」,有效期、使用限制都包在 token 內容里,對 cookie 的管理能力依賴較小,客戶端存起來就顯得更自由。但 web 應用的主流方式仍是放在 cookie 里,畢竟少操心。 「token 的過期」**那我們如何控制 token 的有效期呢?很簡單,把「過期時間」和數據一起塞進去,驗證時判斷就好。
編碼的方式豐儉由人。**「base64」**比如 node 端的 cookie-session - npm 庫
默認配置下,當我給他一個 userid,他會存成這樣:
這里的 eyJ1c2VyaWQiOiJhIn0=,就是 {"userid":"abb」} 的 base64 而已。 「防篡改」
是的。所以看情況,如果 token 涉及到敏感許可權,就要想辦法避免 token 被篡改。解決方案就是給 token 加簽名,來識別 token 是否被篡改過。例如在 cookie-session - npm 庫中,增加兩項配置:
這樣會多種一個 .sig cookie,裡面的值就是 {"userid":"abb」} 和 iAmSecret通過加密演算法計算出來的,常見的比如HMACSHA256 類 (System.Security.Cryptography) | Microsoft Docs。
好了,現在 cdd 雖然能偽造出eyJ1c2VyaWQiOiJhIn0=,但偽造不出 sig 的內容,因為他不知道 secret。**「JWT」**但上面的做法額外增加了 cookie 數量,數據本身也沒有規范的格式,所以 JSON Web Token Introction - jwt.io 橫空出世了。
它是一種成熟的 token 字元串生成方案,包含了我們前面提到的數據、簽名。不如直接看一下一個 JWT token 長什麼樣:
這串東西是怎麼生成的呢?看圖:
類型、加密演算法的選項,以及 JWT 標准數據欄位,可以參考 RFC 7519 - JSON Web Token (JWT)node 上同樣有相關的庫實現:express-jwt - npm koa-jwt - npm
token,作為許可權守護者,最重要的就是「安全」。業務介面用來鑒權的 token,我們稱之為 access token。越是許可權敏感的業務,我們越希望 access token 有效期足夠短,以避免被盜用。但過短的有效期會造成 access token 經常過期,過期後怎麼辦呢?一種辦法是,讓用戶重新登錄獲取新 token,顯然不夠友好,要知道有的 access token 過期時間可能只有幾分鍾。另外一種辦法是,再來一個 token,一個專門生成 access token 的 token,我們稱為 refresh token。
有了 refresh token 後,幾種情況的請求流程變成這樣:
如果 refresh token 也過期了,就只能重新登錄了。
session 和 token 都是邊界很模糊的概念,就像前面說的,refresh token 也可能以 session 的形式組織維護。狹義上,我們通常認為 session 是「種在 cookie 上、數據存在服務端」的認證方案,token 是「客戶端存哪都行、數據存在 token 里」的認證方案。對 session 和 token 的對比本質上是「客戶端存 cookie / 存別地兒」、「服務端存數據 / 不存數據」的對比。**「客戶端存 cookie / 存別地兒」**存 cookie 固然方便不操心,但問題也很明顯:
存別的地方,可以解決沒有 cookie 的場景;通過參數等方式手動帶,可以避免 CSRF 攻擊。 「服務端存數據 / 不存數據」
前面我們已經知道了,在同域下的客戶端/服務端認證系統中,通過客戶端攜帶憑證,維持一段時間內的登錄狀態。但當我們業務線越來越多,就會有更多業務系統分散到不同域名下,就需要「一次登錄,全線通用」的能力,叫做「單點登錄」。
簡單的,如果業務系統都在同一主域名下,比如wenku..com tieba..com,就好辦了。可以直接把 cookie domain 設置為主域名 .com,網路也就是這么乾的。
比如滴滴這么潮的公司,同時擁有didichuxing.com xiaojukeji.com didiglobal.com等域名,種 cookie 是完全繞不開的。這要能實現「一次登錄,全線通用」,才是真正的單點登錄。這種場景下,我們需要獨立的認證服務,通常被稱為 SSO。 「一次「從 A 系統引發登錄,到 B 系統不用登錄」的完整流程」
**「完整版本:考慮瀏覽器的場景」**上面的過程看起來沒問題,實際上很多 APP 等端上這樣就夠了。但在瀏覽器下不見得好用。看這里:
對瀏覽器來說,SSO 域下返回的數據要怎麼存,才能在訪問 A 的時候帶上?瀏覽器對跨域有嚴格限制,cookie、localStorage 等方式都是有域限制的。這就需要也只能由 A 提供 A 域下存儲憑證的能力。一般我們是這么做的:
圖中我們通過顏色把瀏覽器當前所處的域名標記出來。注意圖中灰底文字說明部分的變化。
謝謝大家哦
Ⅲ 來,科普一下JWT
1. JSON Web Token是什麼
JSON Web Token (JWT)是一個開放標准(RFC 7519),它定義了一種緊湊的、自包含的方式,用於作為JSON對象在各方之間安全地傳輸信息。該信息可以被驗證和信任,因為它是數字簽名的。
2. 什麼時候你應該用JSON Web Tokens
下列場景中使用JSON Web Token是很有用的:
Authorization (授權) : 這是使用JWT的最常見場景。一旦用戶登錄,後續每個請求都將包含JWT,允許用戶訪問該令牌允許的路由、服務和資源。單點登錄是現在廣泛使用的JWT的一個特性,因為它的開銷很小,並且可以輕松地跨域使用。
Information Exchange (信息交換) : 對於安全的在各方之間傳輸信息而言,JSON Web Tokens無疑是一種很好的方式。因為JWTs可以被簽名,例如,用公鑰/私鑰對,你可以確定發送人就是它們所說的那個人。另外,由於簽名是使用頭和有效負載計算的,您還可以驗證內容沒有被篡改。
3. JSON Web Token的結構是什麼樣的
JSON Web Token由三部分組成,它們之間用圓點(.)連接。這三部分分別是:
因此,一個典型的JWT看起來是這個樣子的:
接下來,具體看一下每一部分:
Header
header典型的由兩部分組成:token的類型(「JWT」)和演算法名稱(比如:HMAC SHA256或者RSA等等)。
例如:
然後,用Base64對這個JSON編碼就得到JWT的第一部分
Payload
Public claims : 可以隨意定義。
下面是一個例子:
對payload進行Base64編碼就得到JWT的第二部分
Signature
為了得到簽名部分,你必須有編碼過的header、編碼過的payload、一個秘鑰,簽名演算法是header中指定的那個,然對它們簽名即可。
例如:
簽名是用於驗證消息在傳遞過程中有沒有被更改,並且,對於使用私鑰簽名的token,它還可以驗證JWT的發送方是否為它所稱的發送方。
看一張官網的圖就明白了:
4. JSON Web Tokens是如何工作的
在認證的時候,當用戶用他們的憑證成功登錄以後,一個JSON Web Token將會被返回。此後,token就是用戶憑證了,你必須非常小心以防止出現安全問題。一般而言,你保存令牌的時候不應該超過你所需要它的時間。
無論何時用戶想要訪問受保護的路由或者資源的時候,用戶代理(通常是瀏覽器)都應該帶上JWT,典型的,通常放在Authorization header中,用Bearer schema。
header應該看起來是這樣的:
伺服器上的受保護的路由將會檢查Authorization header中的JWT是否有效,如果有效,則用戶可以訪問受保護的資源。如果JWT包含足夠多的必需的數據,那麼就可以減少對某些操作的資料庫查詢的需要,盡管可能並不總是如此。
如果token是在授權頭(Authorization header)中發送的,那麼跨源資源共享(CORS)將不會成為問題,因為它不使用cookie。
下面這張圖顯示了如何獲取JWT以及使用它來訪問APIs或者資源:
5. 基於Token的身份認證 與 基於伺服器的身份認證
5.1. 基於伺服器的身份認證
在討論基於Token的身份認證是如何工作的以及它的好處之前,我們先來看一下以前我們是怎麼做的:
HTTP協議是無狀態的,也就是說,如果我們已經認證了一個用戶,那麼他下一次請求的時候,伺服器不知道我是誰,我們必須再次認證
傳統的做法是將已經認證過的用戶信息存儲在伺服器上,比如Session。用戶下次請求的時候帶著Session ID,然後伺服器以此檢查用戶是否認證過。
這種基於伺服器的身份認證方式存在一些問題:
Sessions : 每次用戶認證通過以後,伺服器需要創建一條記錄保存用戶信息,通常是在內存中,隨著認證通過的用戶越來越多,伺服器的在這里的開銷就會越來越大。
Scalability : 由於Session是在內存中的,這就帶來一些擴展性的問題。
CORS : 當我們想要擴展我們的應用,讓我們的數據被多個移動設備使用時,我們必須考慮跨資源共享問題。當使用AJAX調用從另一個域名下獲取資源時,我們可能會遇到禁止請求的問題。
CSRF : 用戶很容易受到CSRF攻擊。
5.2. JWT與Session的差異
相同點是,它們都是存儲用戶信息;然而,Session是在伺服器端的,而JWT是在客戶端的。
Session方式存儲用戶信息的最大問題在於要佔用大量伺服器內存,增加伺服器的開銷。
而JWT方式將用戶狀態分散到了客戶端中,可以明顯減輕服務端的內存壓力。
Session的狀態是存儲在伺服器端,客戶端只有session id;而Token的狀態是存儲在客戶端。
5.3. 基於Token的身份認證是如何工作的
基於Token的身份認證是無狀態的,伺服器或者Session中不會存儲任何用戶信息。
雖然這一實現可能會有所不同,但其主要流程如下:
注意:
5.4. 用Token的好處
無狀態和可擴展性: Tokens存儲在客戶端。完全無狀態,可擴展。我們的負載均衡器可以將用戶傳遞到任意伺服器,因為在任何地方都沒有狀態或會話信息。
安全: Token不是Cookie。(The token, not a cookie.)每次請求的時候Token都會被發送。而且,由於沒有Cookie被發送,還有助於防止CSRF攻擊。即使在你的實現中將token存儲到客戶端的Cookie中,這個Cookie也只是一種存儲機制,而非身份認證機制。沒有基於會話的信息可以操作,因為我們沒有會話!
還有一點,token在一段時間以後會過期,這個時候用戶需要重新登錄。這有助於我們保持安全。還有一個概念叫token撤銷,它允許我們根據相同的授權許可使特定的token甚至一組token無效。
5.5. JWT與OAuth的區別
寫在最後:我為大家准備了一些適合於1-5年以上開發經驗的java程序員面試涉及到的絕大部分面試題及答案做成了文檔和學習筆記文件以及架構視頻資料免費分享給大家(包括Dubbo、Redis、Netty、zookeeper、Spring cloud、分布式、高並發等架構技術資料),希望可以幫助到大家。
Ⅳ JWT與Session的比較
如今,越來越多的項目開始採用JWT作為認證授權機制,那麼它和之前的Session究竟有什麼區別呢?今天就讓我們來了解一下。
JWT是什麼
定義
特點
使用JWT來傳輸數據,實際上傳輸的是一個字元串,這個字元串就是所謂的json web token字元串。所以廣義上,JWT是一個標準的名稱;狹義上,JWT指的就是用來傳遞的那個token字元串。這個串有兩個特點:
結構
它由三部分組成:header(頭部)、payload(載荷)、signature(簽名),以.進行分割。(這個字元串本來是只有一行的,此處分成3行,只是為了區分其結構)
和Session的區別
為什麼我們要把JWT和Session做對比呢?因為我們主要在每一次請求的認證時會用JWT,在此之前我們都是用Session的。那這兩者的區別在哪兒呢?
本身的含義
看了前面的介紹,我們發現JWT這個字元串其實本身就包含了關於用戶的信息,比如用戶名、許可權、角色等。
Session傳遞的sessionId雖然是一個更簡單的字元串,但它本身並沒有任何含義。
所以一般說來JWT的字元串要比sessionId長,如果你在JWT中存儲的信息越長,那麼JWT本身也會越長。
而Cookie的存儲容量是有限制的(通常為4KB),所以大家在使用的時候需要注意。
解析方法
JWT的header和payload其實是有json轉變過來的,而signature其實就是一個加密後的字元串,因此解析起來較為簡單,不需要其他輔助的內容。
sessionId是伺服器存儲的用戶對象的標識,理論上需要一個額外的map才能找出當前用戶的信息。
管理方法
JWT理論上用於無狀態的請求,因此其用戶管理也只是依賴本身而已。我們一般是在它的payload中加入過期時間,在不增加額外管理的情況下,它只有自動過期的方式。
Session因為它本就是存儲在伺服器端的,因此管理方案就有很多,而且大多都很成熟。
跨平台
JWT本身就是基於json的,因此它是比較容易跨平台的,可以從官網下載不同平台的包,解析即可。
session的跨平台可能就不那麼好做了,需要考慮的地方在於用戶信息存儲的格式,ProtoBuf、json、xml等,管理的話可能就需要專門的統一登錄平台,這個就不展開了。
時效性
無狀態JWT一旦被生成,就不會再和服務端有任何瓜葛。一旦服務端中的相關數據更新,無狀態JWT中存儲的數據由於得不到更新,就變成了過期的數據。
session就不一樣了,sessionId本身就沒有太多含義,只需修改服務端中存儲的數據即可。
適用場景
JWT
JWT的最佳用途是一次性授權Token,這種場景下的Token的特性如下:
真實場景的例子——文件託管服務,由兩部分組成:
如何把JWT用在這個場景中呢?
Session
Session比較適用於Web應用的會話管理,其特點一般是:
總結