基本上每一個系統都會有一個認證功能,這個認證功能其實就是我們平時所做的登錄。用戶通過輸入自己的用戶名和密碼,我們後臺查詢數據庫,如果輸入都正確,那麼就給你登錄進入系統,同時後端保存下session信息。反之如果用戶名或密碼不正確則告訴用戶登錄失敗。今天介紹的兩位主角(JWT、RSA)就和認證有關
這一篇沒有代碼。
平時我們自己寫登錄功能的話,業務邏輯就是上面說的那樣。可是現在我們介紹的Security已經寫好了認證的功能,我們只需要引入依賴,稍作配置就可以"開箱即用"了。
這裏現在的Java web
應用一般分爲兩種,一種就是傳統開發,一種是分佈式開發。認證的的場景也是分爲這兩種。
傳統開發
先說一下傳統開發,傳統開發就是我們基本做的項目,所有的業務、controller、DAO、配置文件、前端頁面、各種靜態資源...
都堆在一個工程中,並把它們統一打成一個jar/war在發佈到線上。
這時我們的登錄邏輯,也比較簡單,就是判斷用戶名和密碼是否正確,正確則保存session
信息,錯誤,則轉發回登錄頁,並要求重新登錄。
但是某一天系統流量大了之後,一個服務器扛不住了怎麼辦,就比如淘寶,雙11或618,一瞬間的高併發訪問量,不僅網站資源承受高併發訪問,認證功能這裏也是,想想一下子也會有很多用戶進行訪問,這樣單個服務器也會面臨死機的風險。
接下來針對這種情況,我們就介紹今天的主角們登場了。
分佈式開發
簡單先介紹一下分佈式開發,這個在之前的博客中也有記錄到,就是把各種模塊都打散,比如用戶模塊放到一個服務器,訂單模塊放到另外一個服務器等等。認證模塊也是同理,將認證相關的模塊單獨放到一個服務器中。這麼可以提高耦合性,同時提高了容錯率,可以面對高併發的場景。。
但是有一個問題,認證模塊單獨佔一個服務器,那麼假設用戶登錄成功之後,我們把用戶信息保存至session
中,接着用戶訪問別的模塊,由於它們不是在同一臺服務器上,那麼session
是不能共享的。別的模塊怎麼判斷你是否登錄了呢?
有些朋友可能會想到一個東西叫global-session
,它的確可以共享session
,但是今天不是用這個。這裏就要介紹第一個主角:
分佈式開發中的單點登錄
單點登錄的實現分兩大環節:
-
用戶認證: 這一環節主要是用戶向認證服務器發起認證請求,認證服務器給用戶返回一個成功的令牌token,
主要在認證服務器中完成,即圖中的A系統,注意A系統只能有一個。 -
身份校驗: 這一環節是用戶攜帶token去訪問其他服務器時,在其他服務器中要對token的真僞進行檢驗,主
要在資源服務器中完成,即圖中的B系統,這裏B系統可以有很多個。
這裏的關鍵就是token
,在A服務器中登錄成功拿到token
後,返回給用戶,然後用戶訪問別的服務器時就需要帶着這個token
了。
接着有情第二位主角:
JWT
從分佈式認證流程中,我們不難發現,這中間起最關鍵作用的就是token,token的安全與否,直接關係到系統的健壯性,這裏我們選擇使用JWT來實現token的生成和校驗。
JWT,全稱JSON Web Token,官網地址https://jwt.io,是一款出色的分佈式身份校驗方案。可以生成token,也可以解析檢驗token。
它其實就是在分佈式的環境中負責token
的生成和驗證的。
JWT生成的token由三部分組成:
-
頭部: 主要設置一些規範信息,簽名部分的編碼格式就在頭部中聲明。
-
載荷:token中存放有效信息的部分,比如用戶名,用戶角色,過期時間等,但是不要放密碼,會泄露!
-
簽名:將頭部與載荷分別採用base64編碼後,用“.”相連,再加入鹽,最後使用頭部聲明的編碼類型進行編
碼,就得到了簽名。
從JWT生成的token組成上來看,要想避免token被僞造,主要就得看簽名部分了,而簽名部分又有三部分組成,其中頭部和載荷的base64編碼,幾乎是透明的,毫無安全性可言,那麼最終守護token安全的重擔就落在了加入的鹽上面了!
試想:**如果生成token所用的鹽與解析token時加入的鹽是一樣的。豈不是類似於中國人民銀行把人民幣防僞技術公開了?**大家可以用這個鹽來解析token,就能用來僞造token。
這時,我們就需要對鹽採用非對稱加密的方式進行加密,以達到生成token與校驗token方所用的鹽不一致的安全效果!
而這個非對稱加密,就是第三位主角:
RSA
-
基本原理:同時生成兩把密鑰:私鑰和公鑰,私鑰隱祕保存,公鑰可以下發給信任客戶端
-
優點:安全,難以破解
-
缺點:算法比較耗時,爲了安全,可以接受
-
歷史:三位數學家Rivest、Shamir 和 Adleman 設計了一種算法,可以實現非對稱加密。這種算法用他們三
個人的名字縮寫:RSA。
這個非對稱加密有分爲兩種:
- 私鑰加密,持有私鑰或公鑰纔可以解密
- 公鑰加密,持有私鑰纔可解密
我們一般使用的是私鑰加密,爲什麼呢?
這裏試想一下,如果我們分佈式系統中,在認證模塊裏通過公鑰加密後,那麼別的模塊只能放置私鑰了。如果有人做壞事,他自己拿公鑰加密(公鑰是暴露的),那麼加密出來,他可以直接拿去訪問別的模塊,從而不用登錄。那這個RSA算法就是形同虛設了。
這時候換成私鑰加密,別的模塊放置公鑰,如果別人拿公鑰(他只能拿公鑰)僞造加密,那別的模塊因爲放置的是公鑰的,也解密不了,所以僞造失敗。
平時我們用到的還是私鑰加密。
今天就記錄到這裏,後續會接着記錄Security的相關知識。幫到忙的話就多多關注下我哦~