1.什麽是JWT?
JSON Web Token(JWT)是壹個開放標準(RFC 7519)。JWT定義了壹個緊湊的、自包含的標準,旨在將各個主題的信息打包成JSON對象。主題信息通過數字簽名進行加密和驗證。HMAC算法或RSA(公鑰/私鑰非對稱加密)算法常用於JWT簽名,安全性高。
2.JWT的結構
JWT的結構由三部分組成:報頭、有效載荷和簽名。所以JWT通常的格式是xxxxx.yyyyy.zzzzz
2.1.頁眉
報頭通常由兩部分組成:令牌類型(即JWT)和使用的算法類型,如HMAC、SHA256和RSA。例如:
使用Base64作為JWT的第壹部分,不建議將敏感信息放在JWT的報頭中。
2.2.有效載荷
以下是有效負載部分的示例:
作為JWT的第二部分,不建議將敏感信息放在JWT的有效載荷中。
2.3.簽名
要創建簽名部分,您需要用密鑰加密Base64編碼的頭和有效負載。加密算法的公式如下:
簽名可用於驗證郵件在傳遞過程中是否已被更改。對於用私鑰簽名的令牌,它還可以驗證JWT的發送者是否是它所說的那個人。
3.JWT是如何運作的
客戶端獲得JWT後,對於後續的每個請求,不再需要通過授權服務判斷請求用戶和用戶的權限。在微服務系統中,使用JWT可以實現單點登錄。認證流程圖如下:
4.案例工程結構
工程原理示意圖如下:
5.構建授權服務授權服務。
UserServiceDetail.java
UserRepository.java
實體類用戶需要實現UserDetails接口,實體類角色需要實現GrantedAuthority接口。
User.java
Role.java
Jks文件生成需要使用Java keytool工具,保證Java環境變量ok。輸入以下命令:
其中,-alias選項是別名,-keyalg是加密算法,-keypass和-storepass是密碼選項,-keystore是jks的文件名,-validity是配置的jks文件的過期時間(單位:天)。
生成的jks文件被用作私鑰,該私鑰只允許由授權服務持有,並用於通過加密生成JWT。只需將生成的jks文件放在auth-service模塊的src/main/resource目錄下即可。
對於諸如用戶服務之類的資源服務,需要使用jks的公鑰來解密JWT。獲取jks文件公鑰的命令如下:
該命令要求安裝openSSL下載地址,然後手動將openssl.exe的安裝目錄配置到環境變量中。
輸入密碼fzp123後,會顯示很多信息。只需提取公鑰,如下所示:
創建壹個新的public.cert文件,將上述公鑰信息復制到public.cert文件中並保存。並將該文件放在資源服務(如user-service)的src/main/resources目錄中。至此,auth-service已經建立。
Maven在編譯項目時可能會編譯jks文件,導致jks文件亂碼,最終無法使用。您需要向pom.xml文件添加以下內容:
6.構建用戶服務資源服務
註入壹個JwtTokenStore類型的Bean,初始化JWT轉換器JwtAccessTokenConverter,並設置用於解密JWT的公鑰。
要配置資源服務的身份驗證管理,除了用於註冊和登錄的接口之外,所有接口都需要進行身份驗證。
創建壹個新的配置類GlobalMethodSecurityConfig,並通過註釋@EnableGlobalMethodSecurity打開方法級安全驗證。
將授權服務模塊的用戶、角色和用戶資料檔案庫復制到該模塊。寫壹個方法在服務層的userService中插入壹個用戶,代碼如下:
為用戶密碼加密配置工具類BPwdEncoderUtil:
為用戶註冊實現壹個API接口/用戶/註冊。代碼如下:
在服務層的userServicedetail中添加壹個login()方法,代碼如下:
AuthServiceClient作為佯裝客戶端,通過遠程調用auth-service interface/oauth/token獲得JWT。在request /oauth/token的API接口中,需要將授權信息、認證類型(grant_type)、用戶名(username)和密碼(password)傳入請求頭,代碼如下:
其中AuthServiceHystrix是AuthServiceClient的保險絲,代碼如下:
JWT包含access_token、token_type、refresh_token等信息,代碼如下:
UserLoginDTO包含用戶和JWT成員屬性,用於返回數據的實體:
登錄異常類UserLoginException
全局異常處理部分類ExceptionHandle
在Web層的UserController類中添加壹個登錄API接口/user/login,如下所示:
啟動三個服務:尤裏卡服務、授權服務和用戶服務。
7.使用郵遞員測試
由於沒有權限,訪問被拒絕。在數據庫中手動添加ROLE_ADMIN權限,並將其與用戶相關聯。再次登錄並獲取JWT,然後再次請求/user/foo接口。
在這種情況下,用戶通過登錄界面獲得授權服務的加密JWT。在用戶成功獲得JWT之後,他們需要在將來訪問資源服務的每個請求中攜帶JWT。資源服務通過公鑰解密JWT。解密成功後,可以獲得用戶信息和權限信息,從而判斷JWT對應的用戶是誰,擁有什麽權限。
壹次獲得壹個令牌,多次使用,資源服務就不再每次訪問令牌對應的用戶信息和用戶權限信息。
壹旦用戶信息或權限信息發生變化,令牌中存儲的相關信息並未發生變化,需要重新登錄才能獲得新的令牌。即使重新獲得令牌,如果原始令牌沒有過期,它仍然可以使用。壹種改進的方法是在成功登錄後將獲得的令牌緩存在網關中。如果用戶的權限更改,請刪除網關上的緩存令牌。當請求通過網關時,判斷所請求的令牌是否存在於緩存中,如果不存在,則提示用戶重新登錄。