ESS 认证鉴权(Aegis.Authorization.ESS)
当你的系统需要对接 ESS 平台,既要完成用户认证,又要按 ESS 返回的资源权限控制接口访问,或者还需要用客凭访问其他服务时,可以接入 Aegis.Authorization.ESS。这是当前认证与鉴权组里功能最完整、依赖关系也最复杂的实现组件。
组件概览
| 字段 | 说明 |
|---|---|
| 组件名称 | ESS 认证鉴权 |
| 真实类库 | Aegis.Authorization.ESS |
| 父级组件 | Aegis.Core.Authentication、Aegis.Core.Authorization |
| 引入方式 | Component.deps.json,可叠加手动注册 Redis 会话和客凭管理器 |
| 组件声明 | EssAuthorize |
| 核心能力 | ESS 登录、Token 校验、资源权限获取、客凭校验、客凭获取 |
| 是否可扩展 | 是 |
| 目标框架 | net8.0 |
| 注册入口 | src/Authorization/Aegis.Authorization.ESS/ServiceCollectionExtensions.cs |
如果把基础认证和基础授权看作底座,那么 ESS 就是在这个底座上补齐了“真实认证中心”和“真实权限来源”。它既会注册 IAuthenticationManager,也会注册 IAuthorizationManager,因此适合需要统一登录、统一接口鉴权和跨服务访问的企业场景。
如何引入
NuGet 包
| 角色 | NuGet 包 | 是否必需 | 说明 |
|---|---|---|---|
| 认证基础层 | Aegis.Core.Authentication | 是 | 提供认证链路和当前用户上下文 |
| 授权基础层 | Aegis.Core.Authorization | 是 | 提供 ApiAuthorize 和权限缓存 |
| 具体实现 | Aegis.Authorization.ESS | 是 | 提供 ESS 的认证与授权实现 |
| Redis 扩展 | Aegis.Caching.Redis | 按需 | 用于 Redis 会话和客凭缓存 |
Component.deps.json
ESS 同时有服务注册和中间件加载,推荐完整写法如下:
{
"Components": {
"Services": [
"Authentication",
"Authorization",
"EssAuthorize"
],
"Middlewares": [
"Authentication",
"Authorization",
"EssAuthorize"
]
}
}
其中:
Authentication:负责用户 Token 认证链路Authorization:负责授权过滤和权限缓存EssAuthorize:负责 ESS 认证、ESS 权限来源和ClientAuthorization中间件
如果少了 EssAuthorize 的中间件阶段,客凭校验链路不会完整接入。
配置说明
ESS 场景通常需要同时配置认证开关和 ESS 连接信息:
| 节点 | 类型 | 是否必填 | 说明 | 常见取值 / 示例 |
|---|---|---|---|---|
Auth:EnableAuthentication | bool | 建议是 | 是否启用认证校验 | true |
Auth:EnableAuthorization | bool | 建议是 | 是否启用授权校验 | true |
EssAuthorize:DiscoveryUrl | string | 是 | ESS 认证服务器地址 | https://auth.example.com |
EssAuthorize:AppId | string | 是 | 应用 ID / AppKey | DEMOAPP |
EssAuthorize:AppSecret | string | 是 | 应用密钥 / AppSecret | secret-value |
EssAuthorize:OpenUrl | string | 登录时建议是 | 读取用户扩展信息的开放服务地址 | https://api.example.com/uap-api |
EssAuthorize:ExtendCodes | string | 否 | 额外需要拉取的扩展字段,多个逗号分隔 | JobNo |
最小配置示例:
{
"Auth": {
"EnableAuthentication": true,
"EnableAuthorization": true
},
"EssAuthorize": {
"DiscoveryUrl": "https://auth.example.com",
"AppId": "DEMOAPP",
"AppSecret": "secret-value",
"OpenUrl": "https://api.example.com/uap-api",
"ExtendCodes": "JobNo"
}
}
手动注入与例外情况
如果你需要分布式会话或客凭缓存,建议在宿主项目中再补两类手动注册:
services.AddRedisSource<AegisRedisSource>(ConfigManager.Get<RedisOptions>("Redis"));
services.AddSingleton<IUserManager, EssRedisUserManager<AegisRedisSource>>();
services.AddSingleton<EssTokenManager<AegisRedisSource>>();
适用场景:
- 多实例部署
- 用户会话需要放到 Redis
- 需要调用
EssTokenManager.GetClientToken()获取客凭
快速使用
第一步:按顺序接入 ESS 认证鉴权
确保你已经:
- 安装基础认证、基础授权和
Aegis.Authorization.ESS - 在
Component.deps.json里按顺序加入Authentication、Authorization、EssAuthorize - 配好
Auth和EssAuthorize节点
第二步:调用登录接口
ESS 接入后,可以直接使用:
POST /api/Auth/Login
示例请求体:
{
"userIdentity": "ess-auth-code",
"extendInfo": "http://localhost:4200",
"codeVerifier": "optional-pkce-code-verifier"
}
第三步:访问受保护接口
认证成功后,带上返回的 Bearer Token 访问标记了 ApiAuthorize 的接口。接入正确时,你应该能看到:
- 登录接口返回 Token
- 受保护接口在无权限时返回
403 - 接口权限会按 Token 做缓存,减少重复访问 ESS
具体使用详情
用户 Token 认证
ESS 的认证实现会负责:
- 用登录参数换取 ESS Token
- 解析当前用户信息
- 把
CustomUser写入IUserManager - 在后续请求里校验 Bearer Token 是否有效
登录接口和登出接口仍然沿用基础认证提供的:
POST /api/Auth/LoginPOST /api/Auth/Logout
资源权限控制
ESS 同时注册了 IAuthorizationManager,因此它可以和 ApiAuthorize 组合成真正的权限校验链路:
ApiAuthorize识别当前访问的Method + Path- 从
IResourcePermissionManager中查权限缓存 - 缓存不存在时,通过 ESS 获取权限列表
- 当前接口不在允许范围内时返回
403
当前默认权限缓存时间是 20 分钟。
客凭访问
如果你的服务需要以“客户端身份”访问其他受保护服务,可以使用:
ClientAuthorization请求头EssTokenManager<T>.GetClientToken()
配合 EssAuthorize 的中间件阶段后,系统会自动校验 ClientAuthorization 中的 Bearer Token。
如何扩展
使用 Redis 会话
如果你不希望 ESS 会话只保存在单机内存里,可以改用:
EssRedisUserManager<T>
它更适合 ESS 场景,因为它按用户标识管理会话,和 ESS 登录、登出流程更贴近。
扩展客凭能力
如果你的系统需要频繁调用其他 ESS 保护接口,建议显式注册 EssTokenManager<T>,在业务服务里统一获取和复用客凭 Token。
自定义权限缓存
如果默认的内存权限缓存不适合你的部署形态,可以继续替换 IResourcePermissionManager,保留 ESS 作为权限来源。
常见问题指南
为什么 ESS 组件要同时依赖基础认证和基础授权?
因为 ESS 不是从零搭一套链路,而是在基础认证上补齐登录和 Token 校验,在基础授权上补齐权限来源。少一个底座,能力都会不完整。
为什么 EssAuthorize 还要放进 Middlewares?
因为它有自己的中间件阶段,用于处理和校验 ClientAuthorization。如果你只写到 Services,客凭请求链路不会完整生效。
不接 Redis 能不能先跑起来?
可以。基础认证默认会注入内存版 IUserManager,单机调试可以先用。但只要进入多实例或需要持久化会话的场景,就应该切到 Redis。