1. Cookie-Session 認證
早期互聯網以 web 為主,客戶端是瀏覽器,所以 Cookie-Session 方式最那時候最常用的方式,直到現在,一些 web 網站依然用這種方式做認證。
認證過程大致如下:
- 用戶輸入用戶名、密碼或者用短信驗證碼方式登錄系統;
- 服務端驗證后,返回一個 SessionId [SessionId與用戶信息進行關聯,通過SessionId可以得到用戶信息],客戶端將 SessionID 存到 cookie,下次訪問的時候帶着SessionID;
- 當客戶端再發起請求,自動帶上 cookie 信息,服務端通過 cookie 獲取 Session 信息進行校驗,判斷對應用戶是否存在;
弊端
- 只能在 web 場景下使用,如果是 APP 中,不能使用 cookie 的情況下就不能用了;
- 即使能在 web 場景下使用,也要考慮跨域問題,因為 cookie 不能跨域;
- cookie 存在 CSRF(跨站請求偽造[前后端分離的項目])的風險;
- 如果是分布式服務做了集群,第一次登錄請求訪問的是A服務,第二請求來到了B服務,B服務就沒有第一次請求訪問登錄得到的Session Id. 此時還需要考慮 Session 同步問題;
2. 基於 Cookie-Session 的改造認證
由於傳統的 Cookie-Session 認證存在諸多問題,可以把上面的方案改造一下。改動的地方如下:
- 不用 cookie 做客戶端存儲,改用其他方式,web 場景下讓前端使用 local storage(局部存儲器。它是html5新增的一個本地存儲API),APP 中使用客戶端數據庫,這樣就實現了跨域,並且避免了 CSRF ;
- 服務端也不存 Session 了,把 Session 信息拿出來存到 Redis 等內存數據庫中,這樣即提高了速度,又避免了 Session 同步問題;
經過改造之后變成了如下的認證過程:
- 用戶輸入用戶名、密碼或者用短信驗證碼方式登錄系統;
- 服務端經過驗證,將認證信息構造好的數據結構存儲到 Redis 中,並將 key 值返回給客戶端;
- 客戶端拿到返回的 key,存儲到 local storage 或本地數據庫;
- 下次客戶端再次請求,把 key 值附加到 header 或者 請求體中;
- 服務端根據獲取的 key,到 Redis 中獲取查詢相關value得到認證信息;
弊端:
- 可能存在單點故障的問題,redis宕機后,全部用戶都得重新登錄。
- redis可以做集群解決單點故障問題。但回過頭來一想, 就為了這小小的session我還得為他付出這么多精力,得不償失。
- 也會占用redis的內存,用戶多的話,要占很多redis內存。
3. Token認證
例子:https://blog.csdn.net/qq_20786911/article/details/104687728?utm_source=app&app_version=4.10.0
認證過程大致如下:
- 用戶在登錄表單中輸入用戶名和密碼,然后點擊登錄。服務端會返回一個token。訪問其他接口的時候帶着token。
- 請求通過在請求頭中攜帶token發送登錄請求之后,通過在后端查詢數據庫驗證用戶的合法性。【通常會讓用戶表與token有關聯關系,一般還會對token加密,而且還會設置過期時間。所以會一般采用redis來存儲,key存token,值存用戶相關信息】
- 在每次發送訪問請求時提供token信息(一般是服務器采用filter過濾器或攔截器來判斷),然后根據這個token得到相關用戶信息(如:用戶id)去數據庫查得到用戶信息進行驗證賬號密碼等,通過則讓用戶訪問服務端接口,不通過則拒絕訪問。
弊端:
- 這一切其實和session id沒有本質區別。
- 需要用token去redis數據庫查詢是否有相應用戶。
- 也會占用redis的內存,用戶多的話,要占很多redis內存。
4. 基於Token的JWT認證
JWT:Json web token 是為了在網絡應用環境間傳遞聲明而執行的一種基於JSON傳輸格式的開放標准,可實現無狀態、分布式的Web應用授權。
先說缺點:
使用JWT時,有個十分頭疼的問題。用戶主動注銷,服務器不能讓token主動失效。就是說token沒有過期前,你想讓它提前停止使用,不好意思沒得辦法。
解決思路有幾種,不過都不是很完美。要么你就不解決JWT退出登錄的問題,你在設置對token設置過期的時候,不要設置太久,設置1天,1天過后就失效。
再說優點:
他是一種行業都認可的開發標准,JWT他就是用於web開發的JSON形式的token,我們現在的開發模式都是前后端分離,數據傳輸就是用的JSON。這個token不像第三點的token,現在這個token有標准了。有定義規范了,按照規范來定義使用它,你可以達到不將其保存到redis數據庫。
認證過程大致如下:
- 用戶登陸服務器,服務端驗證用戶賬號密碼,使用secret生成JWT令牌【一般還會設置過期時間,在生成token的時候指定】,然后將令牌返回給客戶端。
- 客戶端訪問服務端的時候,在請求頭中帶上這個令牌,服務端使用secret去驗證令牌是否合法,合法則讓用戶訪問服務器接口,不合法則拒絕。
- 服務器並不保存token,就不用像上述方式,拿到token還得去redis數據庫驗證,根據token得到對應值(一般時用戶的id,拿到用戶id后,判斷用戶存不存在,用戶不存在直接返回用戶不存在,JWT提供了一個verify方法可以用於驗證該TOKEN是否有效[就是密碼正不正確])。(注意理解這里,因為生成的JWT令牌(是按照某種規則生成的,它可以包含用戶信息,比如我們把用戶id或帶有權限標識的用戶JSON數據[做權限校驗]存到JWT令牌,他第二次帶着JWT令牌登錄時,解析JWT令牌得到他的用戶id,此時拿着用戶id去查詢那個用戶信息,得到賬號密碼進行校驗。))。
JWT令牌結構:
Header(頭部) 是token的一部分,用來存放token的類型和編碼方式,通常是使用base-64編碼
Payload(負載) 包含了信息,你可以存放任一種信息,比如用戶信息,產品信息等,它們都是使用base-64編碼方式【編碼方式取決於你在Header中設置的編碼方式】進行存儲
Signature(簽名) 包括了header,payload和密鑰的混合體,密鑰必須安全地保存儲在服務端
發送給服務器的令牌樣子是AAAA(頭部).BBBB(負載).CCCC(簽名)的形式。
Header:
通常由兩部分組成,令牌的類型與所使用的簽名算法。它會被Base64編碼編成JWT結構的第一部分。【Base64編碼:不是一種加密,就是一種編碼,它能被解碼】
{
"alg":"HS256", // 簽名算法 默認 HS256
"typ":"JWT" // 令牌的類型 默認 JWT
}
Payload:
用於包含聲明信息,一般用來聲明用戶數據。它會被Base64編碼編成JWT結構的第二部分。【Base64編碼:不是一種加密,就是一種編碼,它能被解碼】
因為能被解密,所以這里面不要放特別敏感的用戶信息。
{
"name":"zhangsan",
"age":23,
"email":"971410648@qq.com"
}
Signature:
他是基於Header,Payload被Base64編碼后加上我們提供的一個私鑰,這個私鑰只有服務端知道,然后就會將3者使用Header里面指定的簽名算法進行簽名生成JWT。
作用:保證JWT沒有被篡改。
token = `${base64UrlEncode(header)}.${base64UrlEncode(payload)}`.signature)
5. SSO單點登錄
單點登錄:指在公司內部搭建一個公共的認證中心,公司下的所有產品的登錄都可以在認證中心里完成,一個產品在認證中心登錄后,再去訪問另一個產品時,可以不用再登錄,即可獲取登錄狀態。
6. OAuth第三方登錄
7. 總結
- Cookie + Session 歷史悠久,適合於簡單的后端架構,需開發人員自己處理好安全問題。
- 基於Token的JWT 方案對后端壓力小,適合大型分布式的后端架構,但已分發出去的 token ,如果想收回權限,就不是很方便了。
- SSO 單點登錄,適用於中大型企業,想要統一內部所有產品的登錄方式。
- OAuth 第三方登錄,簡單易用,對用戶和開發者都友好,但第三方平台很多,需要選擇合適自己的第三方登錄平台
8. JWT登錄案例:
基於自定義注解+攔截器實現(沒有指定過期時間):https://blog.csdn.net/qq_37992974/article/details/90236581?utm_source=app&app_version=4.10.0
基於自定義注解+攔截器實現(指定過期時間):https://blog.csdn.net/lzm19930310/article/details/109626578?utm_source=app&app_version=4.10.0
不使用注解+攔截器實現:https://blog.csdn.net/weixin_47025166/article/details/125373122
設置過期時間:https://blog.csdn.net/qq_33229669/article/details/87204400?utm_source=app&app_version=4.10.0
如何讓token失效:https://blog.csdn.net/weixin_39777213/article/details/113410928?utm_source=app&app_version=4.10.0