70 lines
3.0 KiB
Markdown
70 lines
3.0 KiB
Markdown
# Auth Specification
|
||
|
||
## Purpose
|
||
|
||
定义后端三级鉴权的执行语义与超级管理员绕过规则,作为所有接口访问控制的统一契约。
|
||
|
||
## Requirements
|
||
|
||
### Requirement: 三级鉴权
|
||
系统 SHALL 对每个接口按三级放行:标注 `@Public` 的接口无需登录即可访问;未标注任何权限装饰器的接口仅校验有效登录态;标注 `@RequirePermissions` 的接口要求登录态且当前用户拥有对应权限码。
|
||
|
||
#### Scenario: 公开接口匿名访问
|
||
- **WHEN** 请求标注 `@Public` 的接口(如登录、刷新 token、接口文档)
|
||
- **THEN** 系统无需 token 即放行
|
||
|
||
#### Scenario: 未标注接口仅校验登录
|
||
- **WHEN** 未登录请求未标注权限装饰器的接口
|
||
- **THEN** 系统返回 401 未登录
|
||
|
||
#### Scenario: 未标注接口登录后放行
|
||
- **WHEN** 已登录用户请求未标注权限装饰器的接口
|
||
- **THEN** 系统放行
|
||
|
||
#### Scenario: 需权限接口无权限码
|
||
- **WHEN** 已登录用户请求 `@RequirePermissions('user:create')` 的接口,但其权限集不含 `user:create`
|
||
- **THEN** 系统返回 403 无权限
|
||
|
||
### Requirement: 权限集入上下文
|
||
登录成功 SHALL 将用户的权限码集合(其全部角色经资源关联聚合得到的 api/button 资源 code)载入请求上下文,供权限守卫校验。
|
||
|
||
#### Scenario: 登录聚合权限
|
||
- **WHEN** 用户登录成功
|
||
- **THEN** 系统按用户全部角色的 role_resource 关联聚合出权限码集合并载入上下文
|
||
|
||
### Requirement: 超级管理员绕过
|
||
拥有 `code=super_admin` 角色的用户 SHALL 绕过权限码校验;其列表查询的数据权限按「全部」处理,不受 data_scope 过滤。
|
||
|
||
#### Scenario: 超管访问任意需权限接口
|
||
- **WHEN** 拥有 `super_admin` 角色的用户请求任意 `@RequirePermissions` 接口
|
||
- **THEN** 系统无需校验其是否拥有该权限码即放行
|
||
|
||
#### Scenario: 超管查看全量数据
|
||
- **WHEN** 超管执行列表查询
|
||
- **THEN** 系统不做 data_scope 部门过滤,返回全量数据
|
||
|
||
### Requirement: 待改密门禁
|
||
系统 SHALL 对 `must_change_password=true` 的用户实施门禁:除「修改本人密码」与「登出」接口外,其余接口返回 403(提示需先修改密码)。
|
||
|
||
#### Scenario: 待改密访问受保护接口
|
||
- **WHEN** 待改密用户请求除改密/登出外的任意接口
|
||
- **THEN** 系统返回 403 并提示需先修改密码
|
||
|
||
#### Scenario: 待改密改密与登出放行
|
||
- **WHEN** 待改密用户请求修改密码或登出接口
|
||
- **THEN** 系统放行
|
||
|
||
### Requirement: 登录返回待改密标志
|
||
登录成功 SHALL 在响应中返回 mustChangePassword,值为该用户是否待改密。
|
||
|
||
#### Scenario: 待改密登录
|
||
- **WHEN** 待改密用户登录成功
|
||
- **THEN** 响应含 mustChangePassword=true
|
||
|
||
### Requirement: 改密清除待改密
|
||
用户修改本人密码成功 SHALL 清除其待改密标记。
|
||
|
||
#### Scenario: 改密后清除
|
||
- **WHEN** 待改密用户修改密码成功
|
||
- **THEN** 其 must_change_password 置为 false
|