在之前的文章中,我们学习了使用 Web 浏览器、cURL 和 Postman 进行各种 OAuth 2.0 / OpenID Connect Flow。现在是时候学以致用了。
在使用像 Spring Security 这样的安全框架实现基于 OAuth 2.0 / OpenID Connect 的 Security 时,许多活动都是由框架在幕后执行的。了解框架内部发生的情况非常重要,这样我们才能有效地使用框架。
在本文中,我将简要介绍我们将在 Spring Security OAuth 2 教程系列中使用的基于微服务的示例项目。
示例 Spring Boot 微服务项目 {#示例-spring-boot-微服务项目}
我们将构建一个包含以下组件的微服务示例项目:
- Authorization Server - 这是 OAuth 2.0 授权服务器,将向客户端发放访问令牌。我们将使用 Keycloak 作为授权服务器。
- messages-webapp - 终端用户将使用的基于 Spring MVC 的客户端应用。
- messages-service - Spring Boot REST API(资源服务器)用于管理用户数据(消息),并将由 messages-webapp 应用使用。
- archival-service - Spring Boot 应用可使用定时任务定期处理消息存档。它还提供了一个 API 端点来触发存档过程。该服务将同时扮演资源服务器和客户端的角色。
让我们来了解一下这些组件各自提供的功能。
messages-webapp(客户端) {#messages-webapp客户端}
这是一个使用 Spring MVC 和 Thymeleaf 渲染用户界面的 Spring Boot Web 应用。该应用将受到授权服务器(Keycloak)的保护,并将使用 "授权码模式" 来认证用户身份并获取访问令牌。
- 任何人(包括未经授权的用户)都可以查看消息列表。
- 任何经过认证的用户都可以发布新消息。
- 任何具有 ADMIN 角色的认证用户都可以触发消息存档流程。
messages-service(资源服务器) {#messages-service资源服务器}
这是一个 Spring Boot REST API,用于管理用户数据(消息),并将由 messages-webapp
应用使用。这是一个资源服务器,提供以下 API 端点:
- GET /api/messages - 返回消息列表。可公开访问,无需认证。
- POST /api/messages - 创建一条新消息。任何通过身份认证的用户都可以调用此 API 端点。
- POST /api/messages/archive - 归档超过 N 天的消息。只有具有 ADMIN 或 ADMIN_JOB 角色的认证用户才能调用此 API 端点。
archival-service(资源服务器 & 客户端) {#archival-service资源服务器--客户端}
这是一个 Spring Boot 服务,使用定时任务定期处理消息存档。该服务暴露了一个 API 端点,只有 ADMIN 用户才能触发存档过程。该应用将受到授权服务器(Keycloak)的保护,并将使用 "客户端凭证模式"(Client Credentials Flow)获取访问令牌(access token),以调用 messages-service
的 POST /api/messages/archive
API 端点。
该服务提供以下 API 端点:
- POST /api/messages/archive - 在内部将存档流程委托给
messages-service
。只有具有 ADMIN 角色的认证用户才能调用此 API。
为什么 messages-webapp 不直接调用 messages-service
POST /api/messages/archive
端点?原因是,我想演示一个服务同时充当资源服务器和客户端的场景。
archival-service
是一个资源服务器,提供POST /api/messages/archive
API 端点,同时也是messages-service
的客户端。
Keycloak 设置 {#keycloak-设置}
在前面的文章中,我们已经学习了如何设置 Keycloak 并创建 Realm、客户端和用户。我们将在服务配置中使用类似的 Keycloak 设置。
导出和导入 Keycloak Realm 配置 {#导出和导入-keycloak-realm-配置}
如果由于某种原因删除了 keycloak docker 容器,我们就需要再次手动创建 Realm、客户端和用户。我们可以使用 Keycloak 的导出和导入功能来导出 Realm 配置,并在需要时将其导入。
一旦 keycloak 实例启动并运行,我们就可以创建 Realm、客户端和用户,然后使用以下步骤导出 Realm 配置。
$ docker ps
# 复制 keycloak 容器 id
# 通过 ssh 进入 keycloak 容器
$ docker exec -it <container-id> bash
# 导出 Realm 配置和用户信息
$ /opt/keycloak/bin/kc.sh export --dir /opt/keycloak/data/import --realm sivalabs --users realm_file
# 推出容器
$ exit
# 将导出的 Realm 配置复制到本地计算机上
$ docker cp <container-id>:/opt/keycloak/data/import/sivalabs-realm.json ~/Downloads/sivalabs-realm.json
导出 Realm 配置文件后,将其复制到示例项目的 realm-config
文件夹中。然后,你就可以使用 docker-compose
自动导入它了,方法如下:
version: '3.8'
name: spring-security-oauth2-microservices-demo
services:
keycloak:
image: quay.io/keycloak/keycloak:22.0.3
command: ['start-dev --import-realm']
volumes:
- ./realm-config:/opt/keycloak/data/import
container_name: keycloak
hostname: keycloak
environment:
- KEYCLOAK_ADMIN=admin
- KEYCLOAK_ADMIN_PASSWORD=admin1234
ports:
- "9191:8080"
如果还有什么不清楚的地方,不要担心,我将在接下来的文章中详细介绍这个示例项目。
总结 {#总结}
在本文中,我们学习了本 Spring Security OAuth 2 教程系列中的微服务示例项目。在下一篇文章中,我们将详细介绍如何创建 messages-webapp 应用、设置 Keycloak 进行访问控制。
参考:https://www.sivalabs.in/spring-security-oauth2-tutorial-microservices-project-setup/