當前位置:編程學習大全網 - 源碼下載 - 單點登錄JWT與Spring Security OAuth

單點登錄JWT與Spring Security OAuth

通過 JWT 配合 Spring Security OAuth2 使用的方式,可以避免 每次請求 遠程調度 認證授權服務。 資源服務器 只需要從 授權服務器 驗證壹次,返回 JWT。返回的 JWT 包含了 用戶 的所有信息,包括 權限信息

1. 什麽是JWT

JSON Web Token(JWT)是壹種開放的標準(RFC 7519),JWT 定義了壹種 緊湊 自包含 的標準,旨在將各個主體的信息包裝為 JSON 對象。 主體信息 是通過 數字簽名 進行 加密 驗證 的。經常使用 HMAC 算法或 RSA( 公鑰 / 私鑰 非對稱性加密 )算法對 JWT 進行簽名, 安全性很高

2. JWT的結構

JWT 的結構由三部分組成:Header(頭)、Payload(有效負荷)和 Signature(簽名)。因此 JWT 通常的格式是 xxxxx.yyyyy.zzzzz。

2.1. Header

Header 通常是由 兩部分 組成:令牌的 類型 (即 JWT)和使用的 算法類型 ,如 HMAC、SHA256 和 RSA。例如:

將 Header 用 Base64 編碼作為 JWT 的 第壹部分 ,不建議在 JWT 的 Header 中放置 敏感信息

2.2. Payload

下面是 Payload 部分的壹個示例:

將 Payload 用 Base64 編碼作為 JWT 的 第二部分 ,不建議在 JWT 的 Payload 中放置 敏感信息

2.3. Signature

要創建簽名部分,需要利用 秘鑰 對 Base64 編碼後的 Header 和 Payload 進行 加密 ,加密算法的公式如下:

簽名 可以用於驗證 消息 傳遞過程 中有沒有被更改。對於使用 私鑰簽名 的 token,它還可以驗證 JWT 的 發送方 是否為它所稱的 發送方

3. JWT的工作方式

客戶端 獲取 JWT 後,對於以後的 每次請求 ,都不需要再通過 授權服務 來判斷該請求的 用戶 以及該 用戶的權限 。在微服務系統中,可以利用 JWT 實現 單點登錄 。認證流程圖如下:

4. 案例工程結構

工程原理示意圖如下:

5. 構建auth-service授權服務

UserServiceDetail.java

UserRepository.java

實體類 User 和上壹篇文章的內容壹樣,需要實現 UserDetails 接口,實體類 Role 需要實現 GrantedAuthority 接口。

User.java

Role.java

jks 文件的生成需要使用 Java keytool 工具,保證 Java 環境變量沒問題,輸入命令如下:

其中,-alias 選項為 別名 ,-keyalg 為 加密算法 ,-keypass 和 -storepass 為 密碼選項 ,-keystore 為 jks 的 文件名稱 ,-validity 為配置 jks 文件 過期時間 (單位:天)。

生成的 jks 文件作為 私鑰 ,只允許 授權服務 所持有,用作 加密生成 JWT。把生成的 jks 文件放到 auth-service 模塊的 src/main/resource 目錄下即可。

對於 user-service 這樣的 資源服務 ,需要使用 jks 的 公鑰 對 JWT 進行 解密 。獲取 jks 文件的 公鑰 的命令如下:

這個命令要求安裝 openSSL 下載地址,然後手動把安裝的 openssl.exe 所在目錄配置到 環境變量

輸入密碼 fzp123 後,顯示的信息很多,只需要提取 PUBLIC KEY,即如下所示:

新建壹個 public.cert 文件,將上面的 公鑰信息 復制到 public.cert 文件中並保存。並將文件放到 user-service 等 資源服務 的 src/main/resources 目錄下。至此 auth-service 搭建完畢。

maven 在項目編譯時,可能會將 jks 文件 編譯 ,導致 jks 文件 亂碼 ,最後不可用。需要在 pom.xml 文件中添加以下內容:

6. 構建user-service資源服務

註入 JwtTokenStore 類型的 Bean,同時初始化 JWT 轉換器 JwtAccessTokenConverter,設置用於解密 JWT 的 公鑰

配置 資源服務 的認證管理,除了 註冊 登錄 的接口之外,其他的接口都需要 認證

新建壹個配置類 GlobalMethodSecurityConfig,通過 @EnableGlobalMethodSecurity 註解開啟 方法級別 安全驗證

拷貝 auth-service 模塊的 User、Role 和 UserRepository 三個類到本模塊。在 Service 層的 UserService 編寫壹個 插入用戶 的方法,代碼如下:

配置用於用戶密碼 加密 的工具類 BPwdEncoderUtil:

實現壹個 用戶註冊 的 API 接口 /user/register,代碼如下:

在 Service 層的 UserServiceDetail 中添加壹個 login() 方法,代碼如下:

AuthServiceClient 作為 Feign Client,通過向 auth-service 服務接口 /oauth/token 遠程調用獲取 JWT。在請求 /oauth/token 的 API 接口中,需要在 請求頭 傳入 Authorization 信息, 認證類型 ( grant_type )、用戶名 ( username ) 和 密碼 ( password ),代碼如下:

其中,AuthServiceHystrix 為 AuthServiceClient 的 熔斷器 ,代碼如下:

JWT 包含了 access_token、token_type 和 refresh_token 等信息,代碼如下:

UserLoginDTO 包含了壹個 User 和壹個 JWT 成員屬性,用於返回數據的實體:

登錄異常類 UserLoginException

全局異常處理 切面類 ExceptionHandle

在 Web 層的 UserController 類中新增壹個登錄的 API 接口 /user/login 如下:

依次啟動 eureka-service,auth-service 和 user-service 三個服務。

7. 使用Postman測試

因為沒有權限,訪問被拒絕。在數據庫手動添加 ROLE_ADMIN 權限,並與該用戶關聯。重新登錄並獲取 JWT,再次請求 /user/foo 接口。

在本案例中,用戶通過 登錄接口 來獲取 授權服務 加密後的 JWT。用戶成功獲取 JWT 後,在以後每次訪問 資源服務 的請求中,都需要攜帶上 JWT。 資源服務 通過 公鑰解密 JWT, 解密成功 後可以獲取 用戶信息 權限信息 ,從而判斷該 JWT 所對應的 用戶 是誰,具有什麽 權限

獲取壹次 Token,多次使用, 資源服務 不再每次訪問 授權服務 該 Token 所對應的 用戶信息 和用戶的 權限信息

壹旦 用戶信息 或者 權限信息 發生了改變,Token 中存儲的相關信息並 沒有改變 ,需要 重新登錄 獲取新的 Token。就算重新獲取了 Token,如果原來的 Token 沒有過期,仍然是可以使用的。壹種改進方式是在登錄成功後,將獲取的 Token 緩存 網關上 。如果用戶的 權限更改 ,將 網關 上緩存的 Token 刪除 。當請求經過 網關 ,判斷請求的 Token 在 緩存 中是否存在,如果緩存中不存在該 Token,則提示用戶 重新登錄

  • 上一篇:比較實用的選股指標有哪些?
  • 下一篇:易安全源代碼
  • copyright 2024編程學習大全網