认证与资源权限
预计阅读时间: 8 分钟 预计阅读时间: 8 分钟Summerrs Admin 的认证体系由 summer-auth 和 summer-system 共同完成。summer-auth 负责 JWT、会话和令牌校验,summer-system 提供登录、刷新、登出、在线设备、菜单权限和后端 API 资源权限。主应用启动时会注册这些相关插件:
crates/app/src/router.rs 会把 summer-system 这一组路由挂到 /api:
summer-system/src/router/mod.rs 再给整组接口挂上认证层和资源权限层:
请求进入系统接口时,顺序可以理解为:
JWT 配置
开发和生产环境都可以通过 [auth] 配置认证参数:
支持的 JWT 算法来自 summer-auth/src/config.rs: HS256、HS384、HS512、RS256、RS384、RS512、ES256、ES384、EdDSA。
HMAC 系列使用 jwt_secret; 非对称算法使用 jwt_private_key 和 jwt_public_key 指向 PEM 文件。默认从 Header 取 token。开启 is_read_cookie = true 后会尝试读 Cookie,Cookie 模式建议配合 CSRF 防护一起启用。
登录与刷新
系统登录接口在 summer-system/src/router/auth.rs:
实际访问路径是:
LoginDto 使用 #[serde(rename_all = "camelCase")],所以字段是 userName 和 password。返回体中的 data 是:
登录流程如下:
- 根据
sys.user.user_name查询用户。 - 检查账号状态,禁用用户直接拒绝。
- 用 Argon2 校验密码。
- 通过
sys.user_role -> sys.role读取角色编码。 - 通过
sys.role_menu -> sys.menu读取启用的 Button 权限,取auth_mark作为权限码。 - 调用
SessionManager::login签发 access/refresh token。 - 异步写入登录日志。
刷新接口是公开接口:
刷新时会先解析 refresh JWT 拿到用户 ID,再从数据库加载最新角色和权限,最后校验 Redis 中的 refresh key 并轮转新的 refresh token。
Access 与 Refresh 的职责
Access JWT 是自包含的。summer-auth/src/token/jwt.rs 的 AccessClaims 包含:
Refresh JWT 只保存 sub、typ、iat、exp 和 rid。rid 对应 Redis 中的 auth:refresh:{rid}。
Redis 会话 key 主要有三类:
max_devices = 5 时,第 6 个设备登录会清掉最早登录的设备。concurrent_login = false 时,新登录会清掉该用户所有旧设备。
公开路由
#[public] 和 #[no_auth] 会在编译期通过 inventory 注册公开路由。AuthLayer::for_group(group) 启动时会把同一 group 下的公开路由合并到 PathAuthConfig.exclude。
系统公开接口包括:
其他 summer-system 接口默认都需要登录。
如果路由宏无法自动推导公开路径,可以显式写:
Handler 权限宏
多数管理接口在 handler 上使用声明式权限宏:
权限码来自 sys.menu 中 menu_type = Button 且 enabled = true 的 auth_mark。permission_matches 支持这些匹配:
PermBitmapPlugin 启动时从 sys.menu.bit_position 加载 PermissionMap。映射存在时,登录会把权限列表压缩为 JWT 的 pb 字段;映射缺省时,JWT 会保存 permissions 数组。位图的价值主要是压缩 token 体积,通配符匹配仍在解码后的权限字符串上完成。
后端 API 资源权限
除了 handler 上的 #[has_perm],系统还提供一层后端 API 资源权限:
ResourcePermissionPlugin 启动时加载启用的 sys.resource,再查它们绑定的按钮权限,生成内存策略。SysResourceService 在创建、更新、启停、删除资源或保存绑定后都会调用 reload_policy() 热更新策略。
资源权限层的判定规则很务实:
- 请求尚未注入登录会话时跳过,交给 AuthLayer 或公开路由处理。
- 匹配到已登记资源且绑定了动作权限时,用户只要拥有任意一个绑定权限即可通过。
- 匹配到已登记资源但尚未绑定动作权限时,暂时放行,方便灰度录入资源。
- 未登记资源默认放行,用于兼容旧接口。
因此,生产环境要同时维护两件事: handler 上的 #[has_perm] 不能随意缺失,sys.resource 与按钮绑定也要逐步补齐。
设备与强制下线接口
认证路由还提供设备管理:
online.rs 提供管理员视角的在线用户管理:
登出、踢设备和角色权限变更都通过 auth:deny:{login_id} 触发旧 access token 刷新。deny = "refresh:{ts}" 表示 iat <= ts 的旧 token 需要刷新;deny = "banned" 表示账号被封禁,access 和 refresh 都拒绝。
操作日志
系统路由大量使用 #[log]:
#[log] 会注入 OperationLogContext,捕获 method、URL、query、User-Agent、客户端 IP、登录会话中的用户和耗时。日志不会在请求主链路同步写库,而是推到 OperationLogCollector,由 LogBatchCollectorPlugin 批量写入 sys.operation_log。
敏感接口应该显式关闭参数或响应记录,例如登录和重置密码使用 save_params = false。
