淺析權限認證中的有狀態和無狀態

前言

咱們在設計構建一個系統的時候,權限管理和用戶認證是最基本功能,其中關於用戶認證這塊是一個比較常見的模塊。在已有的方案中,咱們最多見的就是保存到 tomcat 中的 session 對象中。隨着微服務的興起,一種新的認證方法又火了起來,那就是JWT,下面我就淺析下本身對兩種認證方式的認識,一些經驗和你們探討。web

淺談認證

我對認證的理解就是,當一個設備(客戶端)向一個設備(服務端)發送請求的時候,服務端如何判斷這個客戶端是誰。傳統意義有兩種認證方式:有狀態認證、無狀態認證。有狀態和無狀態最大的區別就是服務端會不會保存客戶端的信息。面試

有狀態認證

有狀態的認證,以 cookie - session 模型爲例,當客戶端第一次請求服務端時候,服務端會返回客戶端一個惟一標識(默認在cookie中),並保存對應的客戶端信息。客戶端接受到惟一標識以後,將標識位保存到本地cookie中,之後的每次請求都攜帶此 cookie ,服務端根據此 cookie 標識能夠判斷請求的用戶是誰,而後查到對應用戶的信息,大概示意圖以下:redis

請求認證過程(以tomcat爲例):

一、客戶端向服務端發起請求;算法

二、第一次客戶端發起請求,服務端建立一個 key 爲JSESSIONID的值,並寫入到客戶端的cookie中,同時在服務端的Session Manager中建立一個對象,保存這個 JSESSIONID 對應的信息;spring

三、之後客戶端每次請求,都會根據cookie進行區別,咱們能夠經過 session.setAttrbutie,session.getAttrbuite 等方法,拓展用戶信息,根據用戶信息作一些業務判斷等;數據庫

四、Session Manger 中維護有一個定時器,當 JSESSIONID 對應的信息長時間沒有訪問(默認30分鐘),或者顯性調用 session.invalidate 方法,那麼這個對應的信息將會被刪除。跨域

那麼針對有狀態的認證,咱們分析下他的利弊:瀏覽器

優點

由於客戶端的信息都保存在服務端的 Session Manager 中,若是要將客戶端的認證信息取消,只須要將對應的session 信息刪除便可,及時響應,方便快捷。緩存

劣勢

一、由於服務端保存着客戶端的信息,當用戶量特別多時候,服務端須要特別的內存資源;tomcat

二、若是失效時間特別長的狀況下,大量資源被佔用沒法釋放,若是釋放,那麼至關於用戶的註銷登陸;

三、客戶端的信息在服務端中維護,若是服務端爲集羣的場景下,那麼客戶端信息不共享,必須使用分佈式 session 或者其餘方案;

四、cookie有同源策略和跨域限制,部分業務場景下cookie並不能傳遞;

五、部分設備自己不支持cookie或者禁用cookie,還有的手機瀏覽器也不支持cookie。

應用實戰

一、若是公司以集羣式部署多臺服務,那麼能夠採用的策略有:配置負載均衡的路由策略爲hash一致算法(不推薦),若是某個機器停機,那麼會從新分配到新機器,又須要從新登陸;session複製方式(不推薦),複雜度太高;分佈式 session 方案(強力推薦),目前市場上有 spring-session 的依賴,能夠將 session 保存的容器從應用內部抽取到 redis 或者 數據庫中供多個應用使用,實現集中管理,爲了保證設備的兼容性,spring-session提供了將認證方式從cookie修改成header,web網站能夠保存到 SessionStorage,移動端能夠保存到本地緩存中。

二、若是一個公司有多個產品須要共享認證信息,此時須要使用 SSO Server。

無狀態

無狀態的認證,客戶端在提交身份信息,服務端驗證身份後,根據必定的算法生成一個 token 令牌返回給客戶端,以後每次請求服務端,客戶端都須要攜帶此令牌,服務端接受到令牌以後進行校驗,校驗經過後,提取令牌中的信息用來區別用戶,大概的示例圖以下:

請求認證過程:

一、執行登陸操做,用戶端發送帳號密碼等信息;

二、服務端校驗帳號密碼是否正確,若是正確,根據對應的用戶信息和服務端祕鑰生成 JWT 令牌,而後經過response.setHeader 返回給客戶端(此處假設生成了一個名爲 x-auth-token 的令牌);

三、客戶端在返回成功以後,將Header中的x-auth-token 保存到本地的LocalStorage中;

四、客戶端在之後每次請求服務端時候,都在header中攜帶x-auth-token令牌的值;

五、服務端每接受到請求以後,判斷hader中是否包含x-auth-token,token 是否有效,而後經過 BASE 64 算法 decode,根據解密後的參數,判斷當前 token 是否在有效期,所訪問的接口是否有權限等操做。

優點

一、由於服務端不保留客戶端的任何信息,每次只須要經過特定的算法進行校驗,節省了大量存儲空間;

二、方便水平擴容,不須要 SSO Server,只要保證新的應用採用一樣的驗證算法,就能夠驗證經過並得到對應信息。

劣勢

當客戶端的token被盜用,或者須要手動封禁某個用戶的時候,沒辦法對此token進行操做,必須等待token失效(若是在服務端維護token和用戶的關係,技術能夠實現,可是違背無狀態的設計理念)。

應用實戰

一、生成的 token 中攜帶用戶經常使用信息,可是不攜帶用戶的敏感信息,好比密碼手機號等等,由於這些信息經過BASE 64 能夠解密出來的;

二、要處理服務端主動禁用某個 token ,能夠採用黑名單措施,每次請求前判斷當前token是否已經被禁用;

三、token 中的信息除了基本信息外,還應該攜帶好比簽發時間、有效時間、刷新token等字段,用來處理token的續約問題。

總結

在實際的項目中,咱們該如何選擇認證模式,是有狀態的認證仍是無狀態的認證呢?之前看文章時候,在掘金中看到有人把 JWT 批評的一無可取,就和垃圾同樣。我我的以爲吧技術沒有誰好誰壞,誰舊誰新,也沒有誰該被時代淘汰,存在及合理,咱們須要充分理解需求,合理使用技術,只有最合適的技術纔是最好的選擇。 下面是我關於技術選型時候的一些我的觀點,但願你們批評指正和交流。

在個人經驗中,目前比較流行的就是互聯網APP中大部分採用 JWT 的認證方式,一些企業內部管理系統則大部分採用 cookie-session 的機制,大量的商業案例下,我我的分析推測的緣由可能以下:

一、在互聯網APP產品中,尤爲以 to C 模式,用戶量極大,爲了用戶體驗,通常會將登陸信息保留特別長時間,某些APP 只要你不卸載,那麼無論幾個月以後登陸,帳戶仍是處於登陸狀態。在這種狀況下,假如採用 cookie-session 機制,那麼你的用戶信息保存不少個月,用戶量特別大的狀況下,會形成大量資源佔用和浪費,這種場景採用 JWT 就是相對比較好的方案。

二、企業內部管理系統有如下特色:用戶量較少(最多最多不超過10W人),信息安全要求高(及時踢出客戶端登陸狀態,我的瀏覽器關閉帳號退出登陸),在這樣的場景下佔用的內存不會太多,因此基於 cookie-session 這種機制,是比較好的方案,若是企業內部還有其餘應用須要集成時候,須要使用 SSO Server 實現。

代碼案例

最近在找工做,若是閒下來有時間的時候會寫兩個項目出來,敬請期待:

一、 spring security + JWT 的驗證案例

二、shiro + spring-session (header替換cookie)的驗證方案

ps:螞蟻5面技術過了,期待hr面試的早點到來,給本身加油。

相關文章
相關標籤/搜索