Spring Security 6.3基於JWT身份驗證與授權開源專案

banq發表於2024-05-28


Java 後端應用程式使用 Spring-security 實現基於 JWT 的身份驗證和授權,這是一個概念驗證專案,利用 Spring-security 實現基於 JWT 的身份驗證、API 訪問控制、Token 撤銷和洩露密碼檢測。

新發布的 Spring Security 6.3 版本新增了密碼洩露檢測功能,本專案提供的預設實現在底層使用了Have I Been Pwned API 。

向安全端點發出的任何請求都會被 JwtAuthenticationFilter.java 攔截,JwtAuthenticationFilter 會新增到安全過濾器鏈中,
並在 SecurityConfiguration.java 中進行配置。自定義過濾器負責驗證傳入訪問令牌的真實性並填充安全上下文。

關鍵元件:

  • 公共 API 宣告:ApiEndpointSecurityInspector.java
  • Token配置:TokenConfigurationProperties.java
  • Token生成:JwtUtility.java

公共 API 宣告
任何需要公開的 API 都可以用@PublicEndpoint進行註釋。自定義安全過濾器不會評估對已配置 API 路徑的請求,其邏輯由ApiEndpointSecurityInspector.java控制。

下面是一個宣告為公共的示例控制器方法,它將免於身份驗證檢查:

@PublicEndpoint
@GetMapping(value = <font>"/api/v1/something")
public ResponseEntity<Something> getSomething() {
    var something = someService.fetch();
    return ResponseEntity.ok(something);
}

Token生成和配置
應用程式使用訪問令牌 (JWT) 和重新整理令牌,身份驗證成功後,這兩個令牌都會返回給客戶端。JWT 使用 RS512 非對稱金鑰對進行簽名和驗證,其中私鑰(PKCS#8 格式)用於簽名,相應的公鑰用於在呼叫私有端點時進行驗證,這些操作由JwtUtility.java處理。

重新整理令牌是RefreshTokenGenerator生成的隨機 256 位值,並由AuthenticationService根據使用者識別符號儲存在快取中。

可以在活動檔案中配置令牌有效性/到期時間(以分鐘為單位)和非對稱金鑰對.yml。配置的值填充在TokenConfigurationProperties中並由應用程式引用。以下是示例程式碼片段。

com:
  behl:
    cerberus:
      token:
        access-token:
          private-key: ${JWT_PRIVATE_KEY}
          public-key: ${JWT_PUBLIC_KEY}
          validity: 30
        refresh-token:
          validity: 120


API 訪問控制
應用程式根據使用者在系統中的當前狀態實施訪問控制。相應的許可權嵌入到生成的 JWT 中,從而實現無狀態的訪問控制和授權過程。

洩露密碼檢測
為了保護使用者帳戶免遭在資料洩露中暴露的易受攻擊的密碼攻擊,該專案使用了 中新增的洩露密碼檢測功能spring-security:6.3。提供的預設實現在底層使用了Have I Been Pwned API 。

洩露密碼檢查在兩個關鍵場景中進行:

  • 使用者建立:透過使用者建立 API 註冊新使用者時,將檢查提供的密碼。
  • 使用者登入:即使在建立使用者時密碼未被洩露,但密碼也可能在之後被洩露。為了解決這個問題,登入 API 還加入了密碼洩露檢查。

如果在上述任何情況下檢測到密碼被洩露,伺服器將響應以下錯誤:

{
  <font>"Status": "422 UNPROCESSABLE_ENTITY",
 
"Description": "The provided password is compromised and cannot be used for account creation."
}

為了在登入期間恢復密碼洩露的情況,/users/reset-password我們公開了一個新的 API 端點 PUT。此端點接受以下請求主體負載:

{
  <font>"EmailId": "hardik@behl.com",
 
"CurrentPassword": "somethingCompromised",
 
"NewPassword": "somethingSecured"
}

在允許重置密碼之前,還會檢查新密碼是否被破解。
 

相關文章