Skip to content
Back to skills

Auth Code Tester

ASecurity

权限中台鉴权测试 SKILL。负责对开发者集成的鉴权功能进行集成测试和页面测试。 包括:自动生成测试用例、从权限中台接口获取真实鉴权数据、结合业务数据构造正反例、 输出测试结果并回写到测试用例文件。 当"鉴权功能开发完成"、"运行集成测试"、"验证权限控制"、"启动测试"、"测试每个页面"时使用。

  • 417 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 8, 2026
developmenttypescriptsqlapi

Works with

  • api
  • mcp

Security analysis

A100/100

Scanned September 8, 2026

npx -y skills add infometa/workbuddyskills --skill auth-code-tester --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Auth Code Tester?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Auth Code Tester
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/infometa-auth-code-tester/badge)](https://www.skillsdirectory.com/skills/infometa-auth-code-tester)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: auth-code-tester
description: >
  权限中台鉴权测试 SKILL。负责对开发者集成的鉴权功能进行集成测试和页面测试。
  包括:自动生成测试用例、从权限中台接口获取真实鉴权数据、结合业务数据构造正反例、
  输出测试结果并回写到测试用例文件。
  当"鉴权功能开发完成"、"运行集成测试"、"验证权限控制"、"启动测试"、"测试每个页面"时使用。
---

# 权限中台鉴权测试

本 SKILL 负责对业务系统中集成的权限中台鉴权功能进行系统化测试,分为**集成测试**和**页面测试**两个阶段。

> **加载即执行**:当本 SKILL 由 `auth-code-developer` 链式触发时(步骤 9 推送成功后),加载完成即开始集成测试;集成测试全部通过后,**在同一轮回复内**继续执行页面测试。仅当用户**直接输入测试关键词**("启动测试""验证页面"等)单独唤起本 SKILL 时,才按用户指令决定执行范围。

---

## 零、测试用例文件

在项目根路径下维护一个统一的测试用例文件 `auth-test-cases.json`,所有测试用例和历史测试结果均记录于此。

### 文件结构

```json
{
  "version": "1.0",
  "updatedAt": "2026-01-01T00:00:00Z",
  "cases": [
    {
      "id": "tc-001",
      "permissionCode": "Menu_Button_User_Export",
      "feature": "用户导出",
      "type": "integration",
      "scenario": "positive",
      "description": "有权限且有该组织数据的用户可以正常导出",
      "mockAuthData": { },
      "mockBusinessData": { },
      "expectedStatus": 200,
      "expectedDataRule": "all items org_code starts with OA000001.00002234",
      "lastResult": {
        "passed": true,
        "testedAt": "2026-01-01T00:00:00Z",
        "actual": "..."
      }
    }
  ]
}
```

如文件不存在则自动创建;每次测试执行后将结果回写到对应用例的 `lastResult` 字段。

---

## 一、触发模式

### 1.1 集成测试(自动触发)

**触发时机**:`auth-code-developer` SKILL 完成所有鉴权代码生成(步骤 3-8 全部完成)后,自动触发。

**测试范围**:覆盖项目中**所有**已集成鉴权的权限项,逐一验证「功能权限校验 + 数据范围过滤 + 本地超管模式」完整链路。

**执行流程**:见第二章。

**输出**:集成测试报告。**全部通过后**,自动继续执行页面测试。

### 1.2 页面测试(自动触发)

**触发时机**:集成测试全部通过后,自动触发。也可由用户主动发起(关键词:「启动测试」「测试每个页面」「页面测试」「验证页面能正常查到数据」)。

**测试目标**:
1. 每个已集成鉴权的菜单页面**打开不报错**(HTTP 200,无明显错误响应)
2. 每个页面的**数据查询接口能返回数据**(非空列表,且数据符合权限范围过滤)
3. **菜单权限项管理功能可用**:
   - 页面上有进入「菜单权限项管理」的入口(导航菜单、链接或按钮)
   - 进入后能查询到权限项列表数据(接口返回非空)
   - 页面上存在推送按钮(只验证按钮存在,不触发推送)

**测试范围**:所有 `Menu_Page_` 类型的权限项对应的页面路由和数据查询接口,以及菜单权限项管理模块。

**执行流程**:见第三章。

**遇到问题自动修复**:测试发现报错、无数据、入口缺失或推送按钮不存在时,自动定位并修复代码,修复后自动回归测试,直至所有目标通过。

---

## 二、集成测试执行流程

### 步骤 1:收集全量权限项

扫描项目代码,提取所有已集成鉴权的权限项编码(通过 `// ===== 权限控制开始 =====` 标记和 `checkPermission` 调用定位)。

读取 `auth-test-cases.json` 中已有的用例,对比找出:
- 有用例的权限项 → 直接复用
- 无用例的权限项 → 按步骤 2-4 新建用例

### 步骤 2:获取真实鉴权数据

通过 MCP 工具从权限中台获取真实配置,用于构造模拟数据:

```
# 获取数据范围类型列表
mcp_call_tool("hr-auth-copilot", "execute", {
  "command": "mysql_query",
  "args": {
    "sql": "SELECT DISTINCT dim_type_code, dim_type_name FROM v_ai_data_scope ORDER BY dim_type_code",
    "userQuestion": "获取数据范围类型列表"
  }
})

# 获取指定类型的码值列表(如 Org、WorkPlace)
mcp_call_tool("hr-auth-copilot", "execute", {
  "command": "mysql_query",
  "args": {
    "sql": "SELECT dim_item_code, dim_item_parent_code, dim_item_name, dim_item_full_name FROM v_ai_data_scope WHERE dim_type_code = 'Org' LIMIT 10",
    "userQuestion": "获取Org类型的码值列表"
  }
})
mcp_call_tool("hr-auth-copilot", "execute", {
  "command": "mysql_query",
  "args": {
    "sql": "SELECT dim_item_code, dim_item_parent_code, dim_item_name, dim_item_full_name FROM v_ai_data_scope WHERE dim_type_code = 'WorkPlace'",
    "userQuestion": "获取WorkPlace类型的码值列表"
  }
})
```

用返回的真实码值构造鉴权模拟数据(而非随机捏造),确保测试数据与权限中台实际配置一致。

### 步骤 3:获取业务数据

通过用户已写的业务查询逻辑(SQL 或 ORM)从数据库中查询真实业务数据,用于构造正反例:

```typescript
// 查询业务数据,用于判断哪些数据在权限范围内,哪些不在
// 表名和字段名来自 auth.config.json 中的 DATA_SCOPE_FIELD_MAP 配置
const allData = await db.query('SELECT <org_field>, <scope_field> FROM <business_table> LIMIT 100');
```

业务数据必须使用真实查询,不可硬编码,确保测试覆盖真实数据分布。

### 步骤 4:构造测试用例

每个权限项**至少**生成 **2 个正例 + 2 个反例**:

| 用例类型 | 场景 | 鉴权模拟数据 | 业务数据预期 |
|---------|------|------------|------------|
| 正例 1 | 有权限 + 有该范围内的数据 | 包含该权限项 + 具体数据范围码值 | 返回 200,数据均在范围内 |
| 正例 2 | 有权限 + 拥有「全部」特殊值 | 包含该权限项 + All 特殊值 | 返回 200,数据不过滤 |
| 反例 1 | 无该权限项 | 不包含该权限项(空数组或 null) | 返回 403 |
| 反例 2 | 有权限 + 数据不在范围内 | 包含该权限项 + 无交集的范围码值 | 返回 200,data 为空 |

**鉴权模拟数据格式**(模拟 `getUserOperations` 和 `getUserDataScope` 的返回值):

```typescript
// 正例 1 的模拟鉴权数据
const mockAuthPositive1 = {
  operations: ['<permissionCode>'],  // 有权限
  dataScope: {
    success: true, code: '0',
    data: [{
      authid: 'test-001',
      roleCode: 'test-role',
      dataScopes: {
        Org: ['<真实组织码值,来自 MCP>'],
        WorkPlace: ['<真实工作地码值,来自 MCP>']
      }
    }]
  }
};

// 反例 1 的模拟鉴权数据
const mockAuthNegative1 = {
  operations: [],  // 无权限(空数组)
  dataScope: null
};

// 反例 2 的模拟鉴权数据(有权限但范围内无数据)
const mockAuthNegative2 = {
  operations: ['<permissionCode>'],
  dataScope: {
    success: true, code: '0',
    data: [{
      authid: 'test-002',
      roleCode: 'test-role',
      dataScopes: {
        Org: ['<不存在的组织码值,确保无交集>'],
        WorkPlace: ['<不存在的工作地码值>']
      }
    }]
  }
};
```

> **⚠️ 格式示例,禁止直接复用**:以上模拟数据中的权限项编码、码值均为示例,生成时必须替换为实际的权限项编码和 MCP 返回的真实码值。

### 步骤 5:并行执行全量测试

对所有权限项逐一执行测试,在 `local` 模式下注入模拟鉴权数据(不依赖真实权限中台账号):

```typescript
describe('<permissionCode> 鉴权测试', () => {

  it('[正例1] 有权限且数据在授权范围内,应返回过滤后数据', async () => {
    mockAuthService(mockAuthPositive1);
    const res = await callApi('<method>', '<api_path>', userId);
    expect(res.status).toBe(200);
    const data = await res.json();
    expect(data.length).toBeGreaterThan(0);
    // 验证数据均在权限范围内
  });

  it('[正例2] 有权限且拥有全部数据范围,应返回全量数据', async () => {
    mockAuthService(mockAuthPositive2);
    const res = await callApi('<method>', '<api_path>', userId);
    expect(res.status).toBe(200);
    const data = await res.json();
    expect(data.length).toBeGreaterThan(0);
  });

  it('[反例1] 无该权限项,应返回 403', async () => {
    mockAuthService(mockAuthNegative1);
    const res = await callApi('<method>', '<api_path>', userId);
    expect(res.status).toBe(403);
  });

  it('[反例2] 有权限但数据范围内无数据,应返回空列表', async () => {
    mockAuthService(mockAuthNegative2);
    const res = await callApi('<method>', '<api_path>', userId);
    expect(res.status).toBe(200);
    const data = await res.json();
    expect(data.length).toBe(0);
  });
});
```

### 步骤 6:输出集成测试报告并回写

**输出给用户**:

```
=== 集成测试报告 ===
测试时间:2026-01-01 10:00:00
覆盖权限项:5 个
总用例数:20 个(10 正例 + 10 反例)

权限项                        正例    反例    状态
─────────────────────────────────────────────────
Menu_Page_User_Management     2/2     2/2     ✅ 全通过
Menu_Button_User_Export       2/2     2/2     ✅ 全通过
Menu_Button_User_Delete       1/2     2/2     ⚠️ 1 个失败
Menu_Page_Order_List          2/2     2/2     ✅ 全通过
Menu_Button_Order_Delete      2/2     1/2     ⚠️ 1 个失败

失败详情:
[Menu_Button_User_Delete - 正例2] 全部数据范围时返回了过滤后的数据,预期返回全量...
[Menu_Button_Order_Delete - 反例2] 无交集范围时仍返回了数据,数据范围过滤可能未生效...
```

将完整报告回写到 `auth-test-cases.json` 的 `lastResult` 中。

**若存在失败**:自动分析失败原因,修复对应的鉴权代码,修复后重新执行失败的用例,直至全部通过。

**全部通过后**,自动进入第三章「页面测试执行流程」,无需用户确认。

---

## 三、页面测试执行流程

### 步骤 1:检查本地服务是否可访问

在发起任何 HTTP 请求之前,先检查本地服务是否已启动:

```
访问本地服务根路径(如 http://localhost:3000)
  ├─ 可访问(HTTP 200/3xx)→ 继续执行步骤 2
  └─ 不可访问(Connection Refused / 超时)→ 执行启动流程
```

**启动流程**:
1. 扫描项目 `package.json`,识别启动命令(优先顺序:`dev` > `start` > `serve`)
2. 检查 `.env` / `.env.local` 文件是否存在,缺失则提示用户补充后继续
3. 执行启动命令,等待服务就绪(检测到端口监听或健康检查接口返回 200)
4. 就绪后继续步骤 2;若启动失败则输出错误日志,停止并提示用户排查

### 步骤 2:检查菜单权限项管理模块是否已建设

**在进行任何页面测试之前,先检查菜单权限项管理模块是否存在**,根据结果决定后续行动:

```
扫描项目代码,查找菜单权限项管理模块
  ├─ 已存在(有对应路由、列表接口、推送相关代码)
  │     └─ 将菜单权限项管理页面纳入步骤 4 的全面页面测试范围,继续执行步骤 3
  └─ 不存在
        └─ 先调用 auth-code-developer SKILL 建设菜单权限项管理功能,
           建设完成后将其纳入测试范围,再继续执行步骤 3
```

**菜单权限项管理模块的测试要求**(纳入步骤 4 后按此标准验证):
1. 页面上有进入菜单权限项管理的导航入口(导航菜单/侧边栏/顶部菜单)
2. 进入后页面可正常加载(HTTP 200,无错误信息)
3. 权限项列表查询接口返回数据(非空)
4. 页面上存在推送按钮(只验证存在,不触发推送)

以上 4 项全部通过才算菜单权限项管理模块验证通过。

### 步骤 3:收集待测页面

扫描以下来源,收集所有需要测试的页面:
1. `auth-test-cases.json` 中 `permissionCode` 以 `Menu_Page_` 开头的用例
2. 项目代码中通过 `PermissionGuard` / 路由守卫保护的页面路由
3. `.hrright/auth.config.json` 中 `permissions` 数组的顶级节点(`Menu_Page_` 类型)
4. 步骤 2 中确认的菜单权限项管理页面

对每个页面记录:页面路由路径、对应的数据查询接口(`GET` 请求)、绑定的权限项编码(菜单权限项管理页面额外记录推送按钮的 HTML 标识)。

### 步骤 4:确认本地超管模式

确认 `~/.hrright/{sysCode}/local-permissions.json` 存在且包含所有 `Menu_Page_` 权限项(含菜单权限项管理页面的权限项)。若文件不存在或权限项缺失,自动生成/补充后继续。

### 步骤 5:逐页面执行测试

对每个页面依次执行:

#### 5.1 页面加载测试

```
访问页面路由(如 GET /employee-management)
  ├─ HTTP 200 → ✅ 页面加载正常
  ├─ HTTP 4xx/5xx → ❌ 页面加载失败,记录错误
  └─ 响应内容包含明显错误信息(如 stack trace、Error:、Exception)→ ❌ 记录错误
```

#### 5.2 数据查询测试

```
调用该页面的数据查询接口(如 GET /api/employee/list)
  ├─ 返回 200 且 data 不为空 → ✅ 能查询到数据
  ├─ 返回 200 但 data 为空或 null → ⚠️ 接口正常但无数据,检查数据库是否有数据
  ├─ 返回 403 → ❌ 权限校验拦截,检查超管文件是否包含该权限项
  └─ 返回 4xx/5xx 或抛出异常 → ❌ 接口报错,记录错误信息
```

#### 5.3 菜单权限项管理专项验证(仅针对该页面)

```
1. 检查是否存在进入菜单权限项管理的导航入口
   ├─ 在导航菜单/侧边栏/顶部菜单中能找到该入口 → ✅
   └─ 找不到任何入口 → ❌ 记录:缺少菜单权限项管理导航入口

2. 检查页面上是否存在推送按钮(含「推送」、「同步」、「推送到权限中台」等字样)
   ├─ 存在推送按钮 → ✅(不触发,只验证存在)
   └─ 不存在推送按钮 → ❌ 记录:缺少推送按钮
```

### 步骤 6:自动修复 Bug

测试中发现问题时,立即定位并修复,修复完成后告知用户做了什么:

| 问题类型 | 自动修复策略 |
|---------|------------|
| 页面路由 404 | 检查路由配置,修复路由注册或路径拼写错误 |
| 页面响应含错误信息 | 查看响应内容,定位问题组件,修复代码 |
| 接口返回 500 | 查看后端日志,定位异常,修复代码 |
| 接口返回 403 | 检查超管文件权限项列表,补充缺失的权限项编码 |
| 接口返回 200 但 data 为空/null | 检查数据范围过滤逻辑,确认超管模式下数据范围是否为 All |
| 数据库查询报错 | 检查 SQL / ORM 语句,修复字段名、表名或语法错误 |
| 缺少菜单权限项管理导航入口 | 在导航菜单配置中添加菜单权限项管理的导航项 |
| 菜单权限项管理页面报错 | 定位报错组件,修复代码后回归 |
| 权限项列表接口无数据 | 检查查询逻辑,确认 `auth.config.json` 中的权限项定义可被正确读取 |
| 缺少推送按钮 | 在菜单权限项管理页面补充推送按钮及对应事件绑定 |

修复完成后,**立即对相关页面/功能重新执行步骤 5**,验证修复是否生效。

### 步骤 6:输出测试报告

所有页面测试完成(或多次修复后全部通过)后,输出汇总报告:

```
=== 页面测试报告 ===
测试时间:2026-04-16 10:00:00
测试页面数:4 个

页面              路由                      数据查询接口               状态
──────────────────────────────────────────────────────────────────────────
员工管理          /employee                 GET /api/employee/list    ✅ 通过
订单列表          /order                    GET /api/order/list       ✅ 通过
部门管理          /department               GET /api/dept/list        ✅ 通过(自动修复 1 次)

【菜单权限项管理专项】
检查项                              状态
──────────────────────────────────────────────────────────
导航菜单中存在入口                   ✅ 通过
管理页面可正常打开                   ✅ 通过
权限项列表接口返回数据               ✅ 通过
推送按钮存在(未触发)               ✅ 通过

测试结果:3/3 页面通过,菜单权限项管理 4/4 项通过 ✅ 全部通过。
```

**自动修复记录**(若有):
```
[自动修复记录]
页面:部门管理
问题:GET /api/dept/list 返回 500,错误信息:Unknown column 'dept_code' in field list
修复:将字段名 dept_code 改为 department_code(来自步骤1扫描的真实字段名)
回归:修复后重新测试,返回 200,data 包含 12 条记录 ✅
```

### 步骤 7:循环直至全部通过

若仍有页面未通过,**继续修复 + 回归测试**,循环执行步骤 5-6,直至所有页面满足:
- 页面打开不报错(HTTP 200,响应中无明显错误信息)
- 数据查询接口返回数据(`data` 非空且非 null)

---

## 四、测试数据构造规则

### 正例数据构造

1. 从 MCP `hr-auth-copilot.execute`(`mysql_query` 查询 `v_ai_data_scope`)获取真实码值(如真实组织编码)
2. 从数据库查询确认该码值前缀下确实存在业务数据
3. 若无数据,换另一个码值重试,或告知用户数据库中缺少对应测试数据

### 反例数据构造(反例 2:有权限但无数据)

1. 从 MCP 获取真实码值列表
2. 选择一个**确认数据库中没有对应数据**的码值(或构造一个不存在的码值)
3. 确保是「无数据」而非「无权限」,避免混淆两种失败原因

### 「全部」特殊值处理

| 范围类型 | 全部特殊值 |
|---------|-----------|
| `Org` | `Org-All` |
| `WorkPlace` | `WorkPlace-All` |
| 其他 | `global` |

正例 2 必须使用全部特殊值,验证数据范围为「全部」时确实不过滤。

---

## 五、测试不通过时的分析提示

| 失败类型 | 可能原因 | 排查方向 |
|---------|---------|---------|
| 正例返回 403 | 权限项编码拼写错误 / 模拟数据注入未生效 | 检查权限项编码是否与 API 守卫中一致 |
| 正例返回 200 但数据不在范围内 | 数据范围过滤逻辑有误 / 字段映射配置错误 | 检查 `DATA_SCOPE_FIELD_MAP` 中表名和字段名 |
| 反例返回 200(应返回 403) | 路由守卫未生效 / 权限校验被跳过 | 确认 `checkPermission` 在数据查询前执行 |
| 反例 2 有数据(应为空) | 数据范围过滤条件未拼接 / SQL 条件被忽略 | 检查 `buildDataScopeWhere` 的返回值是否正确拼入 SQL |

---

## 六、MCP 工具

测试数据构造时调用:

| 查询目的 | SQL(通过 `hr-auth-copilot.execute` 的 `mysql_query` 命令执行) |
|---------|------|
| 获取全部数据范围类型 | `SELECT DISTINCT dim_type_code, dim_type_name FROM v_ai_data_scope ORDER BY dim_type_code` |
| 获取指定类型下的真实码值 | `SELECT dim_item_code, dim_item_parent_code, dim_item_name, dim_item_full_name FROM v_ai_data_scope WHERE dim_type_code = '<类型编码>'` |

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

View all in development →

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.