抢先一步
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": "http://localhost: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 看板
注释