搶先一步
VMware 提供培訓和認證,助你加速前進。
瞭解更多今天,我很高興地宣佈,你擁有了一項新超能力:使用 Spring Authorization Server 在 Spring Initializr 上建立應用程式!
沒錯,是時候開始你的 OAuth2 之旅,成為你一直以來註定要成為的英雄了!在這篇文章中,我將解釋如何充分利用你的新超能力,以及在哪裡可以瞭解更多資訊。
Spring Authorization Server 是一個構建在 Spring Security 之上的開源框架,它允許你建立自己的基於標準的 OAuth2 Authorization Server 或 OpenID Connect Provider。它實現了各種 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
這將為你提供一個開箱即用、具備以下功能的應用程式
當然,這不止這些,你可以檢視功能列表獲取完整列表。
那麼我們能用這個做什麼呢?使用上面的示例,我們將從最容易理解的 Client Credentials 流程開始。我將使用命令列工具 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,可用於向 OAuth2 資源伺服器發起帶 user.read
作用域的認證請求,以訪問受保護資源。換句話說,只需一個 Spring Boot 應用程式和一些屬性,我們就可以輕鬆地鑄造已簽名的 JWT,並開始使用 OAuth2 保護應用程式。當然,使用 Spring Security 設定資源伺服器也同樣簡單,但那將留給你來測試你未知曉的超能力。
為了簡單起見,我們使用 Introspection 端點來測試此令牌。
注意:請記住令牌將在 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://: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 結合 Spring Authorization Server 建立你自己的個人 OAuth2 和 OpenID Connect 練兵場。
當你準備好時,我鼓勵你閱讀參考指南,它包含所有可用功能和配置選項的詳細資訊。我特別推薦如何:使用社交登入進行身份驗證這個指南,作為學習和探索的好方法。
也許瞭解 OAuth2 和 Spring Authorization Server 的最好方法是構建一個包含(至少)三個應用程式的示例 OAuth2 架構
檢視可用的示例,它們展示了這三個應用程式,並嘗試只使用 Spring Initializr 構建你自己的!一旦你完成了,未來就完全取決於你了!
現在去拯救世界吧!
專案主頁 | GitHub 問題跟蹤器 | ZenHub 看板
註釋