目錄:
一、JWT介紹
二、基於spring cloud + zuul + jwt 實戰
三、源碼地址
一、JWT介紹:
JSON Web Token(JWT)是一個非常輕巧的規範。這個規範允許我們使用JWT在用戶和服務器之間傳遞安全可靠的信息。
讓我們來假想一下一個場景。在A用戶關注了B用戶的時候,系統發郵件給B用戶,並且附有一個鏈接“點此關注A用戶”。鏈接的地址可以是這樣的
https://your.awesome-app.com/make-friend/?from_user=B&target_user=A
上面的URL主要通過URL來描述這個當然這樣做有一個弊端,那就是要求用戶B用戶是一定要先登錄的。可不可以簡化這個流程,讓B用戶不用登錄就可以完成這個操作。JWT就允許我們做到這點。
JWT的組成
一個JWT實際上就是一個字符串,它由三部分組成,頭部、載荷與簽名。
JWT的適用場景
我們可以看到,JWT適合用於向Web應用傳遞一些非敏感信息。例如在上面提到的完成加好友的操作,還有諸如下訂單的操作等等。
其實JWT還經常用於設計用戶認證和授權系統,甚至實現Web應用的單點登錄。
優點
因為json的通用性,所以JWT是可以進行跨語言支持的,像JAVA,JavaScript,NodeJS,PHP等很多語言都可以使用。因為有了payload部分,所以JWT可以在自身存儲一些其他業務邏輯所必要的非敏感信息。便於傳輸,jwt的構成非常簡單,字節佔用很小,所以它是非常便於傳輸的。它不需要在服務端保存會話信息, 所以它易於應用的擴展缺點
一旦拿到token, 可用它訪問服務器,直到過期,中間服務器無法控制它,如是它失效(有解決方案: 在 token 中保存信息,可添加額外的驗證,如加一個 flag, 把數據庫對應的flag失效,來控制token有效性)。
token的過期時間設置很關鍵,一般把它設到凌晨少人訪問時失效,以免用戶使用過程中失效而丟失數據。 - token保存的信息有限,且都是字符串。
安全相關不應該在jwt的payload部分存放敏感信息,因為該部分是客戶端可解密的部分。保護好secret私鑰,該私鑰非常重要。如果可以,請使用https協議有人提到jwt暴露簽名算法(alg),而且會有None(無簽名),所以建議隱去alg。
一般的協議制定都會考慮擴展性和普適性。但是我們在應用中可以採用我們默認的算法,而不是根據alg去處理。
二、基於spring cloud + zuul + jwt 實戰
1、介紹:
本案例採用雙token的方式完成jwt。其中accessToken 用於用戶身份認證。refreshToken用於當accessToken失效時重新生成。
案例做了特別處理,當用戶退出時,要主動將accessToken失效(redis維護),降低accessToken暴露的可能性。當accessToken做失效處理時,允許一定時間的容錯時間(配置文件可設置),目的是避免併發訪問時的異常。
2、實戰源碼
項目結構:
流程:
1、用戶登錄:
用戶登錄,zuul網關過濾器將訪問跳轉至認證微服務。在認證微服務驗證用戶名、密碼,驗證通過後生成accessToken 和refreshToken(注意:本案例使用用戶密碼當簽名密鑰,這樣就避免了密鑰集中洩密)。過期時間分別設置為1小時 和24小時(配置文件可修改這兩個時間)。
返回兩個token,在前端保存(本案例localStorage)如圖:
2、token認證訪問(accessToken有效):
當訪問需要token認證的url時,zuul網關過濾器將請求轉發至認證微服務,認證微服務通過accessToken驗證是否合法。如果合法,zuul網關繼續執行,訪問其他微服務。
3、token認證訪問(accessToken失效,refreshToken有效):
因為accessToken 的失效時間比refreshToken短,所以當accessToken失效時,refreshToken可能還未失效。因此前端主動發起二次請求,並將refreshToken發送到認證微服務,認證微服務驗證refreshToken有效後,再次生成新的accessToken和refreshToken,並返回給前端,保存。
4、accessToken和refreshToken 都失效
當兩個token都失效時,前端引導用戶到登錄界面,重新登錄。
三、源碼
https://github.com/wzjgn/zktd-bigdata-platform
閱讀更多 技術顧問聯盟 的文章