从 Ctx 上下文到访问控制:rust-web-app 请求上下文设计与 ACS 权限系统路线图(完整指南)
【免费下载链接】rust-web-appCode template for a production Web Application using Axum: The AwesomeApp Blueprint for Professional Web Development.项目地址: https://gitcode.com/gh_mirrors/ru/rust-web-app
rust-web-app 是一个基于Axum框架的生产级 Rust Web 应用模板(AwesomeApp Blueprint),它不仅提供了完整的登录认证与 JSON-RPC 动态路由,还精心设计了Ctx 请求上下文,并为未来的ACS 访问控制(Access Control System)权限系统预留了完整演进路线。本文将带你快速理解这套请求上下文如何贯穿一次 HTTP 请求的完整生命周期,以及 PBAC 权限系统将如何分阶段落地。
一、为什么需要 Ctx 请求上下文?🧭
在很多 Web 框架中,"当前用户是谁"往往散落在 session、header 解析或全局变量里。rust-web-app 的做法更简洁:用一个轻量结构体Ctx承载整个请求的身份上下文,并让它贯穿从 HTTP 中间件到业务模型层的每一层。
核心定义见 ctx/mod.rs:
pub struct Ctx { user_id: i64, /// Note: For the future ACS (Access Control System) conv_id: Option<i64>, }Ctx只有两个字段,却承担了三重职责:
| 字段 | 职责 | 说明 |
|---|---|---|
user_id | 身份标识 | 当前请求用户的数据库 ID,为0时表示"根/匿名"上下文 |
conv_id | 容器作用域 | 预留字段,为 ACS 按会话(Conv)粒度做权限判定而设计 |
| 结构本身 | 上下文传递 | 作为 JSON-RPC 资源注入每个 RPC 方法,业务层无需再解析请求头 |
Ctx 的三种创建方式
Ctx::root_ctx()—— 系统级/未认证上下文,user_id = 0,用于登录等无需身份的接口(见 handlers_login.rs);Ctx::new(user_id)—— 正常认证用户上下文,且明确拒绝创建 user_id 为 0 的普通上下文(见 ctx/mod.rs),从类型层面杜绝"伪用户";ctx.add_conv_id(conv_id)—— 派生一个带会话作用域的上下文,这是未来 ACS 权限判定的关键扩展点(见 ctx/mod.rs)。
二、从 Cookie 到 Ctx:一次请求的完整旅程 🚀
理解了Ctx是什么,再看它如何被"造出来"。整个流程由 main.rs 中定义的中间件链驱动,执行顺序从外到内为:
请求 → mw_req_stamp(请求打点) → CookieManager(Cookie 管理) → mw_ctx_resolver(解析身份,永不失败) → [/api 路由] mw_ctx_require(强制认证) → 业务 Handler1. mw_ctx_resolver:永不失败的上下文解析器
这是整个认证链最巧妙的设计(见 mw_auth.rs)。它完成四步:
- 取 Cookie—— 从请求 Cookie 中读取认证令牌;
- 查用户—— 通过令牌中的用户名查询
UserForAuth; - 验签—— 校验令牌签名与过期时间;
- 构建 Ctx—— 调用
Ctx::new(user.id)生成上下文,并将结果(含可能的错误)放入请求扩展(request extensions)中传递。
关键在于它的错误策略:resolver 本身永远不会"失败",而是把潜在错误(如令牌缺失、格式错误、验签失败,见 CtxExtError)包装进结果中继续往下传。这样既不妨碍下游中间件执行,又能让需要强制认证的mw_ctx_require或具体 Handler 按需取出精确的错误信息——这是典型的"解析与裁决分离"设计。
2. mw_ctx_require:API 路由的守门员
/api(JSON-RPC)路由通过route_layer单独挂载了 mw_ctx_require,它取出上一步的解析结果,一旦认证失败立即拒绝请求。而登录路由不挂这层,因此无需身份也能访问——权限边界在路由装配时就被清晰划定。
3. 令牌是如何签发的?
登录成功后,api_login_handler 会校验密码(支持多方案哈希与自动升级),并写入令牌 Cookie。令牌格式为ident.exp.sign三段式 Base64URL 编码(见 token/mod.rs):
| 段 | 含义 |
|---|---|
ident | 用户标识(用户名) |
exp | RFC3339 过期时间 |
sign | 用BLAKE3对用户盐值 + 全局密钥计算的签名 |
验签时服务端用相同算法重算签名比对,并检查过期时间(见 validate_token_sign_and_exp)。由于盐值存在数据库中,重置盐值即可让该用户所有旧令牌失效——这是相当优雅的"服务端注销"机制。
三、Ctx 如何流入 JSON-RPC 业务层 🔁
认证完成后,上下文要真正"流"到业务代码中。JSON-RPC 入口 rpc_axum_handler 做了两件事:
- 通过
CtxW提取器从请求扩展中取出Ctx(提取器实现见 mw_auth.rs); - 用
resources_builder![ctx]将 Ctx 作为请求级资源叠加到基础 RPC 路由上。
于是任何 RPC 方法都能像 add_conv_msg 这样直接声明ctx: Ctx参数,上下文自动注入:
pub async fn add_conv_msg( ctx: Ctx, // ← 由框架自动注入 mm: ModelManager, params: ParamsForCreate<ConvMsgForCreate>, ) -> Result<DataRpcResult<ConvMsg>> { ... }至此,Ctx完成了Cookie → 中间件 → 请求扩展 → RPC 资源 → 模型层 BMC的全链路传递,业务代码永远不需要手动"找用户"。
四、ACS 权限系统路线图:PBAC 如何落地 🗺️
项目已经为访问控制埋好了种子。model/acs/mod.rs 中标注着 "TO BE IMPLEMENTED",明确了技术路线:基于权限的访问控制(PBAC, Privilege Based Access Control),并与核心容器结构(Org组织、Space空间、Conv会话)绑定。
1. 现有代码中的"路标"
ConvScopedtrait:让拥有conv_id的实体可以被 Ctx "升级",携带会话作用域参与权限判定(见 conv.rs);- 权限注解草案:ConvBmc::add_msg 的注释中已勾勒出目标 API 形态——
// For access constrol, we will add: // #[ctx_add(conv, space)] // #[requires_privilege_any_of("og:FullAccess", "sp:FullAccess", "conv@owner_id" "conv:AddMsg")]- TODO 校验点:ConvBmc::get_msg 中预留了"先查询、再断言
conv:ReadMsg权限"的检查位。
2. 权限命名与设计思路
从草案注解可以读出清晰的权限分级:og:(Org 组织级)>sp:(Space 空间级)>conv:(会话级),支持"任一权限满足即放行"(requires_privilege_any_of),并支持conv@owner_id这类基于资源属主的动态权限。这与多租户工作区(类似 GitHub 仓库、Discord 服务器)的常见权限模型一致。
3. 落地路线图
| 阶段 | 内容 | 状态 |
|---|---|---|
| ✅ 已完成 | Ctx.conv_id预留字段 +add_conv_id()派生 | 代码已就位 |
| ✅ 已完成 | ConvUser多用户会话成员表(见 conv_user.rs) | 表结构与 BMC 已建 |
| 🔜 规划中 | PBAC 权限模型:Org / Space / Conv三级权限与assert_privileges断言 | 待实现 |
| 🔜 规划中 | 声明式权限宏(#[requires_privilege_any_of]),与现有generate_common_bmc_fns宏风格一致 | 待实现 |
其中Conv实体已区分 OwnerOnly / MultiUsers 两种会话类型,并携带owner_id——这些正是会话级权限判定的数据基础。
五、新手快速上手清单 ✅
想亲手跑起来看看?三步即可:
- 克隆仓库(本地无网络环境可用镜像):
git clone https://gitcode.com/gh_mirrors/ru/rust-web-app - 启动 PostgreSQL(Docker 一行命令,见 README.md "Starting the DB" 一节),并按 sql/dev_initial/ 下的
00-recreate-db.sql、01-create-schema.sql、02-dev-seed.sql初始化数据库; - 运行服务:
cargo run -p web-server
项目结构速览
| 目录 | 职责 |
|---|---|
| crates/libs/lib-core/ | 核心模型层:Ctx上下文、acs权限模块、Conv/ConvMsg 等实体 |
| crates/libs/lib-auth/ | 认证能力:多方案密码哈希、令牌生成与验签 |
| crates/libs/lib-web/ | Web 层:登录 Handler、RPC 动态路由、认证中间件 |
| crates/libs/lib-rpc-core/ | JSON-RPC 参数/结果的通用类型与宏 |
| crates/services/web-server/ | 服务入口:路由装配、RPC 方法注册 |
| crates/tools/gen-key/ | 开发辅助:生成令牌密钥 |
建议的阅读顺序
- 从 ctx/mod.rs 入手,理解上下文本体(仅 50 余行);
- 顺着 mw_auth.rs 走一遍 Cookie → Ctx 的解析链;
- 最后查看 conv.rs 中的权限注释,把握 ACS 的演进方向。
总结 📌
rust-web-app 用一个仅含两个字段的Ctx结构体,就把"身份"这件事从登录、认证中间件到 JSON-RPC 业务层串成了一条清晰可控的链路;而conv_id预留字段、ConvScopedtrait 与 PBAC 权限注解草案,则为下一步的Org → Space → Conv 三级访问控制系统铺好了地基。如果你正在用 Rust 构建生产级 Web 应用,这套"上下文先行、权限渐进"的设计非常值得借鉴。
【免费下载链接】rust-web-appCode template for a production Web Application using Axum: The AwesomeApp Blueprint for Professional Web Development.项目地址: https://gitcode.com/gh_mirrors/ru/rust-web-app
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考