文章

微服务鉴权设计:SpringBoot 3.x + OAuth2

前言

Spring Boot 3 GA 版本在 2022-11-24 已经发布,虽然时间不短了,但是网上关于如何升级和使用 Spring Boot 3 的资料并不是太多。

Spring Boot 3 主要的变化点有:

  • Spring 主版本升级到 6.x

  • JDK 版本至少 17+

  • Javax Servlet 替换成了 Jakarta Servlet

  • SpringFox Swagger 替换成了 SpringDoc

  • 移除对 /META-INF/spring.factories 的支持

  • 更快的启动时间和更低的内存占用

  • 一些配置属性的名称和使用方式发生了变化

  • ......

Spring Security OAuth2 主要的变化点有:

  • 旧的 Spring Security OAuth2 彻底停止维护

  • 官方提供最新的 SDK 组件分别为:

    • spring-boot-starter-oauth2-client

    • spring-boot-starter-oauth2-resource-server

    • spring-boot-starter-oauth2-authorization-server

微服务鉴权场景

前端应用:PC Web、Mobile H5、Mini Program、APP 等

后端微服务应用:一般有三类后台应用,分别是 API GateWay、Auth Service、业务微服务(多个)

OAuth2 组件:授权服务器(Authorization Server)、资源服务器(Resource Server)、客户端(Client)

外部系统:外围业务系统,授权调用本系统的 API 资源等

认证:

- API Gateway: 作为统一的认证中心,所有的请求需经过网关,对 Token 进行验证,非法则报401错误
- Auth Service:作为专门的授权服务器,负责处理用户登录、注册等认证相关操作以及生成和管理 OAuth2 Token 令牌
- 后台业务服务:负责处理具体的业务逻辑,不直接集成 OAuth2 组件,而是信任来自 API Gateway 的请求
- 前端应用:在 API 请求头中加入 Token 令牌,Token 过期重新登录或者 调用 Refresh Token

鉴权:

- API Gateway: 对于认证通过的 API 请求,对登录用户所属角色下的 API 权限资源列表进行校验,判断是否有权限访问
- Auth Service:基于 RBAC 等权限模型设计,保存用户的权限信息,并提供接口给 API Gateway 和前端应用调用
- 前端应用:获取 Auth Service 的用户功能权限数据,渲染用户可以看到的菜单、页面、按钮等

微服务鉴权设计

总体架构图:

image-20240724171908478

认证鉴权流程图:

image-20240718190831198

设计要点:

  1. Auth Service 集成spring-boot-starter-oauth2-authorization-server 打造成统一的授权服务器,负责生成和管理 OAuth2 令牌;也可替换默认的登录页面,自定义登录页面以符合企业的 UI 设计

  2. Auth Service 使用提前准备的 RSA 私钥和公钥来生成 JWT Token,将公钥给到网关,这样在 Auth Service 宕机时,网关也能在 Token 的有效期内不影响接口的访问

  3. Auth Service 进行企业级改造,将授权令牌、客户端信息、授权同意使用数据库进行保存,并使用 JDBC Repository替换配置中基于内存的Spring Bean

  4. Auth Service 需自定义 UserDetailsService 来进行用用户名+密码登录后的用户认证

  5. 将 Auth Service 中对于接口的请求从 authenticated() 改为 permitAll() ,放开授权服务器的资源,统一使用 API Gateway 进行认证

  6. Api Gateway 网关集成spring-boot-starter-oauth2-resource-server 可作为资源服务器,验证请求中的 Token 令牌,并根据用户权限决定是否允许访问资源;同时使用认证服务器生成的公钥进行构建 JWT Decoder,这样在认证服务器不可用时,api gateway 也能够在 token 有效期内进行接口的路由访问

  7. API Gateway 网关集成spring-boot-starter-oauth2-client,可作为 OAuth2 客户端与外部系统或服务进行交互,比如:一些主流的三方Social应用,Github、Google 等

  8. API Gateway 网关可以通过自定义一个授权管理器CustomAuthorizationManager 来验证用户当前身份下的权限列表,比如:API 列表。

  9. 前端应用使用授权码模式来获取到 Access Token 和 Refresh Token,并将 Token 存储到 LocalStorage 中,便于后续请求使用;比如:APP 等应用用户 Token 频繁过期会影响体验,可以通过 Refresh Token 的方式进行 Token 替换;如果 Refresh Token 也过期了,那么就需要重新再次登录一次

  10. 前端应用通过接口获取到当前用户的功能权限,进行菜单、页面和按钮的动态渲染

  11. 三方外部系统作为客户端,通过自身的客户端凭证(client ID 和 client secret)获取访问令牌(access token),不涉及用户授权,流程简单且安全性高

  12. 后台业务微服务之间相互授信,接口交互通过 Header 中直接获取到用户信息,无需再次经过认证授权服务器,减少对于认证授权服务器的性能压力

这样做的好处:

  1. 集中认证与授权:所有的认证和授权逻辑都集中在 API Gateway 和 Auth Service 中,简化了后端业务服务的实现。

  2. 安全性:API Gateway 作为第一道防线,保护后端业务服务不暴露在外部。

  3. 可扩展性:可以轻松添加新的后端业务服务,而无需在每个服务中重复实现认证和授权逻辑。

  4. 维护性:认证和授权逻辑集中在一个地方,便于统一管理和更新。

推荐阅读

权限概念模型设计

附录

OAuth2 组件图:

OAuth2 Roles

查看 OAuth2 授权服务器信息:

image-20240709201324160

获取授权码:

image-20240709201732331

image-20240709202152247

通过授权码获取 access_token:

image-20240709202927331

Oauth2 授权记录表:

image-20240710185253468

Gateway 通过 Token进行接口访问,无 Token 报 401 错误:

image-20240719191439157

image-20240719191523012

License:  CC BY 4.0