JWT 认证(Aegis.Authorization.Jwt)
当你不想依赖外部认证中心,而是希望在应用内生成 Bearer Token、通过登录接口发放 Token 并在后续请求里复用时,可以接入 Aegis.Authorization.Jwt。下面说明当前版本下它的实际接法、能力边界和已知约束。
组件概览
| 字段 | 说明 |
|---|---|
| 组件名称 | JWT 认证 |
| 真实类库 | Aegis.Authorization.Jwt |
| 父级组件 | Aegis.Core.Authentication |
| 子级扩展 | Aegis.Authorization.RedisUserManager |
| 组件定位 | 提供 IAuthenticationManager 的 JWT 实现,用于本地发放与校验登录 Token |
| 引入方式 | Component.deps.json |
| 组件声明 | JwtAuthorize |
| 核心能力 | 登录发放 Token、会话存储、过期检查 |
| 是否可扩展 | 是 |
| 目标框架 | net8.0 |
| 注册入口 | src/Authorization/Aegis.Authorization.Jwt/ServiceCollectionExtensions.cs |
这个组件更适合内部系统、单体服务或受控环境里的本地 Token 场景。当前版本的实现并不是纯粹的“无状态 JWT 网关”,它仍然依赖 IUserManager 保存登录会话,因此部署形态会直接影响 Token 是否跨实例可用。
如何引入
NuGet 包
| 角色 | NuGet 包 | 是否必需 | 说明 |
|---|---|---|---|
| 基础层 | Aegis.Core.Authentication | 是 | 提供认证中间件和当前用户上下文 |
| 具体实现 | Aegis.Authorization.Jwt | 是 | 提供 JWT 登录与 Token 校验实现 |
| 会话扩展 | Aegis.Authorization.RedisUserManager | 按需 | 多实例时用于共享会话 |
Component.deps.json
{
"Components": {
"Services": [
"Authentication",
"JwtAuthorize"
],
"Middlewares": [
"Authentication"
]
}
}
配置说明
JWT 认证当前公开的配置项如下:
| 节点 | 类型 | 是否必填 | 说明 | 常见取值 / 示例 |
|---|---|---|---|---|
Auth:EnableAuthentication | bool | 建议是 | 是否启用认证校验 | true |
JwtAuthorize:Issuer | string | 是 | Token 发行者 | Aegis |
JwtAuthorize:Audience | string | 是 | Token 受众 | Aegis.Api |
最小配置示例:
{
"Auth": {
"EnableAuthentication": true
},
"JwtAuthorize": {
"Issuer": "Aegis",
"Audience": "Aegis.Api"
}
}
补充说明:
- 当前版本没有独立的固定密钥配置节点。
- 登录时传入的
LoginInfo.Password会参与 Token 生成,因此登录接口参数设计需要你自己控制好。
快速使用
第一步:启用基础认证和 JWT 认证
确保你已经:
- 安装
Aegis.Core.Authentication - 安装
Aegis.Authorization.Jwt - 在
Component.deps.json中加入Authentication和JwtAuthorize - 在配置中提供
Issuer与Audience
第二步:调用登录接口获取 Token
JWT 认证接入后,可以直接使用基础认证提供的登录接口:
POST /api/Auth/Login
示例请求体:
{
"userIdentity": "demo-user",
"password": "demo-secret",
"expiresMinutes": 30,
"userModel": {
"name": "Demo"
}
}
第三步:访问受保护接口
拿到登录接口返回的 Token 后,在请求头中带上:
Authorization: Bearer {token}
如果接入正常,你应该能看到:
- 登录接口返回 Token
- 受保护接口可以读取
CurrentUser.Value - Token 过期后,会从会话存储中被移除
具体使用详情
登录与会话关系
当前 JwtAuthenticationManager 的工作方式是:
- 登录时根据
Issuer、Audience和LoginInfo.Password生成 Token - 把生成的 Token 和用户信息写入
IUserManager - 后续请求用 Token 到
IUserManager查回当前用户
这意味着:
- Token 不只是签名串,也同时充当会话索引
- 如果会话存储中没有这个 Token,当前请求就不会被识别为已登录
过期处理
当前实现会在 CheckToken(...) 时检查会话过期时间:
- 未过期:继续返回当前用户
- 已过期:删除用户会话,并把当前登录视为无效
使用边界
这个实现更适合:
- 本地开发和功能验证
- 单实例内部系统
- 需要快速接入 Token 登录,但暂时不依赖外部认证中心的场景
如果你希望 Token 真正独立于会话存储长期有效,当前版本还不适合作为最终的无状态认证方案。
如何扩展
替换会话存储
如果你希望多个实例共享登录状态,可以引入 Redis 用户会话:
services.AddRedisSource<AegisRedisSource>(ConfigManager.Get<RedisOptions>("Redis"));
services.AddRedisUserManager<AegisRedisSource>();
自定义认证实现
如果你需要更严格的 JWT 签名校验、刷新机制或统一密钥策略,建议:
- 自己实现
IAuthenticationManager - 继续复用基础认证的中间件和
CurrentUser
常见问题指南
为什么服务一重启,JWT 就失效了?
因为当前实现会把登录态写入 IUserManager。如果仍在使用默认内存会话,应用重启后数据会全部丢失。
为什么调用 /api/Auth/Logout 会报错?
因为当前版本的 JwtAuthenticationManager.Logout(...) 还没有实现,不适合把它当作完整的登出方案直接使用。
为什么我只配了 Issuer 和 Audience,没有看到独立密钥配置?
因为当前版本公开的 JwtOption 只有这两个字段。登录时用于生成 Token 的密钥并不来自独立配置节点,而是来自登录参数本身。