基础服务调用链路
简要介绍下HZERO基础服务之间的关系以及调用链路,以帮助解决微服务中的一些常见问题及服务配置管理等。下面的链路调用图主要包含七个基础服务、一个鉴权组件、一个业务服务,将从 API 访问网关开始介绍相关流程。可重点关注下 hzero-gateway-helper
中的权限校验流程。
查看大图
注册中心
所有服务都会注册到注册中心上,便于服务发现。hzero-register 是基于 Netflix Eureka
实现的注册中心,项目或产品上可根据实际情况选择其它的注册中心,如 Zookeeper、Nacos、Formula 等。
配置中心
所有服务都可以向配置中心拉取配置,也可以通过配置中心动态更新服务配置。hzero-config 是基于 Spring cloud config
实现的配置中心,项目或产品上可根据实际情况选择其它的配置中心,如 Nacos、Apollo、Formula 等。
API调用链路
① API调用
- 所有API调用都是进入网关,通过网关路由到正确的服务上。对外暴露端口时,只需暴露网关服务的端口即可。
② API鉴权
-
在网关服务内,所有API请求都会经过
GateWayHelperFilter
过滤器,在过滤器中,会调用hzero-gateway-helper
鉴权组件对API及用户鉴权。 -
根过滤器
HelperChain
包含了一系列过滤器来对请求进行鉴权,将按图中的顺序进行校验。认证通过或不通过都会返回相应的状态码,红色部分表示认证失败,绿色部分表示认证通过,具体状态码的含义可参考最后鉴权常见状态码
。 -
一般服务出现 403、500 等问题时,可先查看返回错误码,或检查 hzero-gateway-helper 的日志,看是哪一步校验不通过,对症下药。
③ 获取登录用户
GetUserDetailsFilter
会带着access_token
访问 hzero-oauth 认证服务的/api/user
接口获取用户信息。
④ 返回用户 Principal
-
用户登录后,oauth 服务将 access_token 和用户认证实体(Authentication)关系存储在 redis session 中,在调用 /api/user 时,将通过 access_token 获取 Authentication,并在接口中返回用户信息
Principal
。 -
得到 Principal 后,转换成
CustomUserDetails
。之后,在AddJwtFilter
里将 UserDetails 转成 JwtToken。
⑤ 返回状态码及JwtToken
-
如果认证失败,将返回状态码,并在网关直接返回前端,不会再调用业务服务。
-
如果API要求用户登录,将返回用户的 JwtToken 信息
⑥ 路由到业务服务
- 鉴权通过后,网关将带着 JwtToken,根据路由信息,转发到对应的业务服务上。
- 在业务服务内部,首先
JwtTokenFilter
会将 JwtToken 转换成 UserDetails,并设置到SecurityContextHolder
上下文中,相当于用户在此服务中已登录。之后的程序中就可以通过DetailsHelper.getUserDetails()
得到当前登录用户信息。 - 若要开启此过滤器,需在启动类上配置
@EnableChoerodonResourceServer
注解开启此功能。
⑦ 返回数据
- 之后返回数据,经过网关,再返回到前端。如果服务响应比较慢,就需要调整网关的超时时间。
服务注册监听
服务启动时,会向注册中心注册自己,hzero-admin 服务监听到服务注册后,会拉取服务文档信息,并做如下事情:
- 解析服务路由信息,更新服务(
hadm_service
)及路由信息(hadm_service_route
) - 通知 hzero-iam 服务更新服务API权限(
iam_permission
),并刷新缓存中的服务权限 - 通知 hzero-swagger 服务更新 Swagger 文档信息(
hadm_swagger
)。
如果服务启动时,未及时更新权限或Swagger文档信息,由于有心跳机制,可等注册中心实例下线后再重启服务。
鉴权常见状态码
状态码 | 含义 |
---|---|
SUCCESS_PASS_SITE | 平台层接口权限校验通过,即用户拥有该平台级API权限 |
SUCCESS_PASS_ORG | 租户层接口权限校验通过,即用户拥有该租户级API权限 |
SUCCESS_SKIP_PATH | 该接口为gateway-helper设置的跳过权限校验的接口,允许通过 |
SUCCESS_PUBLIC_ACCESS | 公共接口,允许访问 |
SUCCESS_LOGIN_ACCESS | 登录可访问接口且已经登录,允许访问 |
SUCCESS_ADMIN | 超级管理员用户,且接口为非内部接口,允许访问 |
PERMISSION_WITH_IN | 内部接口禁止访问,只允许服务内部调用 |
PERMISSION_MISMATCH | 未找到与该请求相匹配的权限,Redis缓存或数据库中没有该API |
PERMISSION_NOT_PASS | 该登录用户没有此接口访问权限 |
PERMISSION_NOT_PASS_ORG | 登录用户没有在此租户下的此接口访问权限 |
PERMISSION_ACCESS_TOKEN_NULL | 请求头部没有access_token |
PERMISSION_ACCESS_TOKEN_INVALID | accessToken不合法 |
PERMISSION_ACCESS_TOKEN_EXPIRED | accessToken已过期 |
PERMISSION_GET_USE_DETAIL_FAILED | 通过access_token从oauthServer获取userDetails失败 |
EXCEPTION_GATEWAY_HELPER | gateway-helper 发生异常 |
API_ERROR_ORG_ID | 接口异常。租户级接口路径必须包含organization_id |
PERMISSION_SERVICE_ROUTE | 未找到该请求对应的路由,请在路由管理页面添加路由 |