Files
tiku-backend.net/docs/architecture/authentication-authorization-hardening-plan.md

99 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 认证与授权待补强清单
> 2026-07-29 实施状态可信代理启动校验、外部登录成员生命周期、Redis 跨实例频控与故障关闭、固定目录数据库 Capability、事务化 System Scope 审计、MassTransit EF Bus/Consumer Outbox 与即时 BackgroundJob Consumer、浏览器 Cookie/CSRF 主链路及 endpoint manifest 已落地。本地 RabbitMQ 4.3.4 已验证停机期间事务提交、outbox 积压及重启补发;生产网关 ACL 和生产 Broker 演练仍属于部署验收项。
当前生效规则见 [认证、授权与 Host 安全策略](authentication-authorization-security.md)。本文只记录尚需补强的安全事项,不重复描述已实现体系。
## P0可信代理与 Host fail-closed
- Production 必须配置正式 `PlatformHosts``TrustedProxyAddresses`
- Production 不允许只保留 `localhost` / `127.0.0.1` 作为平台 Host。
- 未受信来源伪造 `X-Forwarded-Host` 不能改变 realm 或 tenant context。
- 受信代理只接受一跳转发,网关必须覆盖客户端伪造的 Forwarded Headers。
- API 公网入口必须只能由受信网关访问。
实现说明:应用已强制 `ForwardLimit=1`Production 缺少正式 Host、显式 `AllowedHosts` 或可信代理地址时启动失败;公网 ACL 和网关覆盖转发头由部署层落实。
验收:
- Host A + Tenant B token 返回 403。
- 未知 Host 的非豁免路径返回 404。
- Production 缺少可信代理或正式平台 Host 时启动失败。
## P0Disabled / Invited 成员生命周期
- 外部身份登录不得静默恢复 Disabled membership。
- Invited membership 不得被微信登录静默激活。
- 首次外部登录是否允许创建学生成员,必须由租户自注册策略控制。
- 成员恢复只能由管理员显式操作并写审计。
实现说明:`TenantAuthPolicy.AllowExternalStudentSelfRegistration` 控制首次外部登录Disabled/Invited 不会被登录激活,管理员成员变更会同步撤销 Session、写审计并发布生命周期事件。
验收:
- Disabled 成员旧 access/refresh 立即失效。
- Disabled 成员不能通过微信 Web 或小程序登录恢复。
- 关闭自注册时,首次外部登录被拒绝。
## P1SaaS Capability 授权
RBAC 只回答“用户是否有操作权限”Capability 负责“租户是否购买、启用并可使用该能力”。
默认组合:
```text
Tenant Active
+ Subscription 有效
+ Module / Feature 可用
+ Operation Permission
+ DataScope / Resource Scope
```
实现说明:`SaasFeature`、显式 `PermissionModule.RequiredFeatureCode`、不可变套餐版本、`TenantFeatureOverride``IFeatureAccessService` 已进入数据库授权链路。未知 Feature、未购买模块和失效订阅均 fail-closed角色绑定保留历史权限但鉴权和菜单只使用当前有效权限。
验收:
- 有 permission 但套餐不含模块,返回 403。
- 套餐包含模块但没有 permission返回 403。
- PastDue / Cancelled / Expired 不能创建新的受限资源。
- 修改套餐后,旧 access token 不需要等待过期即可失去能力。
## P1接口最小权限与 DataScope 审计
- 建立 endpoint authorization manifestmethod、route、realm、module、permission、DataScope、audit action。
- 后台写接口不得只使用 `[Authorize]`
- tenant/platform 权限不得串用。
- `[AllowAnonymous]` 只能出现在白名单路由。
- All-only 资源必须显式声明。
- 新增 Controller action 未进入 manifest 时测试失败。
实现说明:`AuthorizationManifestTests` 对全部 Controller HTTP Action 的 method、route、匿名标记和 policy 生成稳定摘要MVC convention 同时为全部非匿名 Controller endpoint 生成 realm、module、permission、operation、All-only 与 audit action 运行时元数据,变更会触发测试失败并要求安全评审。
验收:
- 列表、详情、创建、更新、删除、批量、导出和 Worker job 使用一致 DataScope。
- 租户 A 管理员不能读取或操作租户 B 数据。
## P1System Scope 审计
- `ITenantExecutionScope` 创建 System Scope 时必须记录 caller、reason、target tenant 和 request/job id。
- 平台操作、Worker、迁移验证和受审计公共题库服务才允许使用 System Scope。
- 跨租户写操作必须落 `AuditLog`
实现说明:`SystemScopeRequest` 强制 caller、reason、target tenant 和 correlation ID没有租户目标时必须显式声明 `IsGlobal`,且 Worker/公共题库不能创建全局 scope。旧参数签名已移除。成功路径的 entered 审计、跨租户业务写入和 completed 审计处于同一 PostgreSQL 事务,异常路径回滚业务并持久化 entered/failed 审计。
验收:
- 未声明 reason 的 System Scope 创建失败。
- Worker scope 不串租户。
- 高风险平台操作都有审计记录。
## P2客户端与协议规范
- 浏览器 token 存储策略在正式前固定:纯 Bearer、本域 BFF 或 cookie 方案只能选一种主链路。
- Access token 继续短期有效,不把角色和权限写入 JWT。
- 登录审计和错误响应避免泄露手机号、openId、邮箱完整值。
- 出现第三方生态登录、开放 API 或多客户端授权需求时,再评估 OpenIddict / OIDC不继续扩展私有协议。
实现说明:浏览器使用 `/api/browser-auth` + Secure/HttpOnly Cookie + Origin/CSRF 校验;原 `/api/auth` Bearer 契约继续供小程序、原生和服务调用。