微服务鉴权设计: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 的用户功能权限数据,渲染用户可以看到的菜单、页面、按钮等
微服务鉴权设计
总体架构图:
认证鉴权流程图:
设计要点:
Auth Service 集成
spring-boot-starter-oauth2-authorization-server
打造成统一的授权服务器,负责生成和管理 OAuth2 令牌;也可替换默认的登录页面,自定义登录页面以符合企业的 UI 设计Auth Service 使用提前准备的 RSA 私钥和公钥来生成 JWT Token,将公钥给到网关,这样在 Auth Service 宕机时,网关也能在 Token 的有效期内不影响接口的访问
Auth Service 进行企业级改造,将授权令牌、客户端信息、授权同意使用数据库进行保存,并使用 JDBC Repository替换配置中基于内存的Spring Bean
Auth Service 需自定义 UserDetailsService 来进行用用户名+密码登录后的用户认证
将 Auth Service 中对于接口的请求从
authenticated()
改为permitAll()
,放开授权服务器的资源,统一使用 API Gateway 进行认证Api Gateway 网关集成
spring-boot-starter-oauth2-resource-server
可作为资源服务器,验证请求中的 Token 令牌,并根据用户权限决定是否允许访问资源;同时使用认证服务器生成的公钥进行构建 JWT Decoder,这样在认证服务器不可用时,api gateway 也能够在 token 有效期内进行接口的路由访问API Gateway 网关集成
spring-boot-starter-oauth2-client
,可作为 OAuth2 客户端与外部系统或服务进行交互,比如:一些主流的三方Social应用,Github、Google 等API Gateway 网关可以通过自定义一个授权管理器
CustomAuthorizationManager
来验证用户当前身份下的权限列表,比如:API 列表。前端应用使用授权码模式来获取到 Access Token 和 Refresh Token,并将 Token 存储到 LocalStorage 中,便于后续请求使用;比如:APP 等应用用户 Token 频繁过期会影响体验,可以通过 Refresh Token 的方式进行 Token 替换;如果 Refresh Token 也过期了,那么就需要重新再次登录一次
前端应用通过接口获取到当前用户的功能权限,进行菜单、页面和按钮的动态渲染
三方外部系统作为客户端,通过自身的客户端凭证(client ID 和 client secret)获取访问令牌(access token),不涉及用户授权,流程简单且安全性高
后台业务微服务之间相互授信,接口交互通过 Header 中直接获取到用户信息,无需再次经过认证授权服务器,减少对于认证授权服务器的性能压力
这样做的好处:
集中认证与授权:所有的认证和授权逻辑都集中在 API Gateway 和 Auth Service 中,简化了后端业务服务的实现。
安全性:API Gateway 作为第一道防线,保护后端业务服务不暴露在外部。
可扩展性:可以轻松添加新的后端业务服务,而无需在每个服务中重复实现认证和授权逻辑。
维护性:认证和授权逻辑集中在一个地方,便于统一管理和更新。
推荐阅读
附录
OAuth2 组件图:
查看 OAuth2 授权服务器信息:
获取授权码:
通过授权码获取 access_token:
Oauth2 授权记录表:
Gateway 通过 Token进行接口访问,无 Token 报 401 错误: