Spring Authorization Server 現已在 Spring Initializr 上線!

工程 | Steve Riesenberg | 2023 年 5 月 24 日 | ...

今天,我很興奮地宣布,您獲得了一種新的超能力:在 Spring Initializr 上使用 Spring Authorization Server 建立應用程式!

沒錯,是時候開始您的 OAuth2 之旅,成為您一直知道自己可以成為的英雄了!在這篇文章中,我將說明如何充分利用您的新超能力,以及從哪裡可以了解更多資訊。

什麼是 Spring Authorization Server?

Spring Authorization Server 是一個建立在 Spring Security 之上的開源框架,可讓您建立自己的基於標準的 OAuth2 授權伺服器或 OpenID Connect 提供者。它實作了各種 OAuth2 和 OIDC 相關規範中提供的許多協定端點,讓您可以更專注於您的應用程式和使用者,而減少關注流程和規範。由於它位於 Spring Security 之上,因此也可以用於建立驗證中心,以將其他驗證協定調整為 OAuth2。

您可以在參考指南上的概觀中了解更多關於 Spring Authorization Server 的資訊。

開始使用

拯救世界免於邪惡生物試圖消滅所有生命的旅程必須從某個地方開始,而您成為 OAuth2 英雄的旅程也沒有什麼不同!要開始使用,請下載這個範例應用程式,或前往 start.spring.io 並將 OAuth2 Authorization Server 依賴項新增至您的專案。

然後,在您最喜歡的 IDE 中開啟專案,並將以下內容新增至 application.properties

spring.security.oauth2.authorizationserver.client.client-1.registration.client-id=admin-client
# the client secret is "secret" (without quotes)
spring.security.oauth2.authorizationserver.client.client-1.registration.client-secret={bcrypt}$2a$10$jdJGhzsiIqYFpjJiYWMl/eKDOd8vdyQis2aynmFN0dgJ53XvpzzwC
spring.security.oauth2.authorizationserver.client.client-1.registration.client-authentication-methods=client_secret_basic
spring.security.oauth2.authorizationserver.client.client-1.registration.authorization-grant-types=client_credentials
spring.security.oauth2.authorizationserver.client.client-1.registration.scopes=user.read,user.write

或者,您可以將 application.properties 重新命名為 application.yml,並新增以下內容

spring:
  security:
    oauth2:
      authorizationserver:
        client:
          client-1:
            registration:
              client-id: "admin-client"
              # the client secret is "secret" (without quotes)
              client-secret: "{bcrypt}$2a$10$jdJGhzsiIqYFpjJiYWMl/eKDOd8vdyQis2aynmFN0dgJ53XvpzzwC"
              client-authentication-methods: "client_secret_basic"
              authorization-grant-types: "client_credentials"
              scopes: "user.read,user.write"

要啟動應用程式,請執行以下命令

./gradlew bootRun

這會為您提供一個具有以下開箱即用功能的應用程式

  • 一個使用 Spring Security 保護的基於 Servlet 的 Web 應用程式
  • 一個符合標準的授權伺服器,帶有一個 Token Endpoint,用於取得 OAuth2 存取權杖 (JWT)
  • 一個產生的記憶體內 RSA 金鑰對,將用於簽署 JWT
  • 一個 JWK-Set Endpoint1,用於取得產生的公開金鑰
  • 一個 OAuth2 Authorization Server Metadata Endpoint2,用於探索授權伺服器配置
  • 一個 OpenID Connect Provider Configuration Endpoint3,用於探索 OIDC 提供者配置
  • 一個 OAuth2 Introspection Endpoint,用於使用不透明權杖或取得關於權杖的資訊(包括 JWT)
  • 一個 OAuth2 Revocation Endpoint,用於撤銷重新整理權杖(或不透明存取權杖)
  • 一個單一的記憶體內用戶端(具有預先雜湊的密碼),已向授權伺服器註冊,以支援用戶端憑證流程

當然,還有更多功能,您可以查看功能列表以取得完整列表。

取得存取權杖

那麼我們可以做什麼呢?使用上面的範例,我們將從用戶端憑證流程開始,這是最容易理解的。我將在命令列上使用 HTTPie 進行示範,您可以在家裡(或工作場所)跟著操作。

執行以下命令

http -f POST :8080/oauth2/token grant_type=client_credentials scope='user.read' -a admin-client:secret

這會產生類似於以下的響應

{
    "access_token": "eyJraWQiOiJhMWZjM2JhOC0zY2IwLTRkZjAtYTQwNS03ZDhhY2YxYTY4NGIiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJhZG1pbi1jbGllbnQiLCJhdWQiOiJhZG1pbi1jbGllbnQiLCJuYmYiOjE2ODQ1MjYzOTgsInNjb3BlIjpbInVzZXIucmVhZCJdLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAiLCJleHAiOjE2ODQ1MjY2OTgsImlhdCI6MTY4NDUyNjM5OH0.sHDGoQGDpdBuhvdiIpFeeCtTUeU860FBeV23rS6Zqb8tjq_Pytj_Y4Xl6pBB2R5rTAZdMg0cwLvICVYBz-x-hGz2UbHFtYGmo24byb3iKGqBb2BjtY5mMuYQOdnW_PgUVV4vtElhTYkkN_uET4CZ3zxIhgPEc2Yvtt0-d2lGwXzkDiHb_US1zDSUO36nqs4cesMD-yzy5tVmr1e2c6Klojyv6nFN1edfTn7Ci5GvEeB4lDnQdm3ZJr4fyxSiSrq7T34ghj6fMqYn_-lazpoc-wWPB5I35NM0TkUyDw2e_XobqIm6oXG0tBDujL2SK6P05n5MDKkGhgsQlT_ER9gmqA",
    "expires_in": 299,
    "scope": "user.read",
    "token_type": "Bearer"
}

響應中的 access_token 是一個已簽署的 JWT,可用於向具有 user.read 範圍的 OAuth2 資源伺服器發出已驗證的請求,以存取受保護的資源。換句話說,透過 Spring Boot 應用程式和幾個屬性,我們能夠輕鬆地產生已簽署的 JWT,並開始使用 OAuth2 保護應用程式。當然,使用 Spring Security 設定資源伺服器同樣簡單,但我會將其留給您作為對您不知道自己擁有的超能力的測試。

內省存取權杖

為了保持簡單,讓我們使用 Introspection Endpoint 測試這個權杖。

注意:請記住,權杖將在 5 分鐘後過期。

執行以下命令,確保將實際的 access_token 貼上以取代範例

export TOKEN=eyJraW...
http -f POST :8080/oauth2/introspect token=$TOKEN -a admin-client:secret

這會產生類似於以下的響應

{
    "active": true,
    "aud": [
        "admin-client"
    ],
    "client_id": "admin-client",
    "exp": 1684526698,
    "iat": 1684526398,
    "iss": "https://127.0.0.1:8080",
    "nbf": 1684526398,
    "scope": "user.read",
    "sub": "admin-client",
    "token_type": "Bearer"
}

如果相反地您看到此響應

{
    "active": false
}

那麼權杖可能已過期。

如果您想更深入地研究並探索正在發生的事情,您可以啟用追蹤記錄以取得額外的偵錯詳細資訊。您也可以將權杖的到期時間縮短到非常短的時間,例如 30 秒,以便更容易取得過期的權杖。

將以下內容新增至您的 application.properties

logging.level.org.springframework.security=trace
spring.security.oauth2.authorizationserver.client.client-1.token.access-token-time-to-live=30s

或者,如果您使用的是 application.yml,請新增以下內容

logging:
  level:
    org.springframework.security: trace

spring:
  security:
    oauth2:
      authorizationserver:
        client:
          client-1:
            registration:
              ...
            token:
              access-token-time-to-live: 30s

然後重新啟動應用程式,並再次嘗試上述步驟。在發出內省請求後,您將看到類似以下的行

FilterChainProxy : Trying to match request against DefaultSecurityFilterChain [...] (1/2)
FilterChainProxy : Securing POST /oauth2/introspect
FilterChainProxy : Invoking DisableEncodeUrlFilter (1/25)
...

有兩件有趣的事情正在發生。在日誌中的幾行之後,您將看到類似以下的輸出

...
FilterChainProxy                   : Invoking OAuth2ClientAuthenticationFilter (14/25)
ProviderManager                    : Authenticating request with JwtClientAssertionAuthenticationProvider (1/18)
ProviderManager                    : Authenticating request with ClientSecretAuthenticationProvider (2/18)
ClientSecretAuthenticationProvider : Retrieved registered client
ClientSecretAuthenticationProvider : Validated client authentication parameters
ClientSecretAuthenticationProvider : Authenticated client secret
OAuth2ClientAuthenticationFilter   : Set SecurityContextHolder authentication to OAuth2ClientAuthenticationToken
...

這告訴我們,用戶端(我們自己的 CLI)已透過 ClientSecretAuthenticationProvider 使用 HTTP 基本驗證成功驗證。這就是為什麼我們收到 200 OK 響應的原因,但最好透過日誌確認權杖內省請求是否成功。在幾行之後,您將看到類似以下的輸出

...
FilterChainProxy                         : Invoking OAuth2TokenIntrospectionEndpointFilter (22/25)
ProviderManager                          : Authenticating request with OAuth2TokenIntrospectionAuthenticationProvider (1/18)
TokenIntrospectionAuthenticationProvider : Retrieved authorization with token
TokenIntrospectionAuthenticationProvider : Did not introspect token since not active
...

在這裡,我們看到 OAuth2TokenIntrospectionAuthenticationProvider 正在處理請求,但權杖未處於活動狀態。因此,我們可以確認請求已成功,並且權杖已過期。

接下來是什麼?

我們僅僅觸及了您可以使用新超能力做的事情的表面!我希望您記住的主要事情是,您現在可以使用 Spring Initializr 建立您自己的個人 OAuth2 和 OpenID Connect 遊樂場,並搭配 Spring Authorization Server。

當您準備好時,我鼓勵您閱讀參考指南,其中包含關於每個功能和可用配置選項的詳細資訊。我特別推薦指南操作指南:使用社交登入進行驗證,作為學習和探索的絕佳方式。

也許了解 OAuth2 和 Spring Authorization Server 的最佳方式是建立一個範例 OAuth2 架構,其中包含(至少)三個應用程式

  1. OAuth2 用戶端(使用 OpenID Connect)
  2. OAuth2 資源伺服器
  3. OAuth2 授權伺服器

查看可用的範例,其中示範了所有這三個應用程式,並嘗試僅使用 Spring Initializr 建立您自己的應用程式!一旦您完成了這項任務,未來就真的取決於您了!

現在去拯救世界吧!

專案頁面 | GitHub Issue | ZenHub Board

註解


  1. 當應用程式執行時,JWK-Set Endpoint 可在 https://127.0.0.1:8080/oauth2/jwks 上取得。
  2. 當應用程式執行時,OAuth2 Authorization Server Metadata Endpoint 可在 https://127.0.0.1:8080/.well-known/oauth-authorization-server 上取得。
  3. 當應用程式執行時,OpenID Connect Provider Configuration Endpoint 可在 https://127.0.0.1:8080/.well-known/openid-configuration 上取得。

取得 Spring 電子報

隨時掌握 Spring 電子報的最新資訊

訂閱

搶先一步

VMware 提供培訓和認證,以加速您的進展。

了解更多

取得支援

Tanzu Spring 在一個簡單的訂閱中提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位檔案。

了解更多

即將到來的活動

查看 Spring 社群中所有即將到來的活動。

查看全部