ephron.ren 功能测试计划
版本: v4.0
日期: 2026-05-03
站点: https://www.ephron.ren/
仓库: https://gitea.ephron.ren/ephron_ren/ephron.ren
一、测试概览
1.1 服务架构
1.2 测试账号
| 角色 |
用户名 |
密码 |
用途 |
| 管理员 |
Elaina_admin |
Elaina2026! |
测试全部管理后台功能 |
| 普通用户 |
Elaina_user |
Elaina2026! |
测试前台功能 + 权限拦截 |
| 邀请码 |
7CQ0-GE9S-L6QS |
- |
注册流程测试 |
1.3 认证机制
- 跨服务 Cookie
ephron_auth,域 .ephron.ren
- RBAC 权限模型:
user(10) < admin(20) < owner(30)
- 细粒度权限键:如
blog.post.create_draft、auth.user.view_active
1.4 优先级定义
| 级别 |
含义 |
说明 |
| P0 |
核心功能 |
阻塞用户使用,必须通过 |
| P1 |
重要功能 |
影响体验,应尽快修复 |
| P2 |
次要功能 |
可延后处理 |
1.5 测试统计
| 版本 |
测试用例数 |
| v3.0 |
366 |
| v4.0 全量 |
453 |
二、测试用例
模块 1:Home 主页 (www.ephron.ren)
1.1 公开页面
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| H-001 |
首页加载 |
访问 / |
HTTP 200,正常渲染 |
无 |
P0 |
| H-002 |
CSS/JS/图片 |
检查所有静态资源 |
全部 200 |
无 |
P0 |
| H-003 |
响应式布局 |
调整窗口宽度至 375px/768px/1440px |
布局自适应,无溢出 |
无 |
P1 |
| H-004 |
导航→博客 |
点击「博客」 |
跳转 blog.ephron.ren |
无 |
P0 |
| H-005 |
导航→画布 |
点击「画布」 |
跳转 canvas.ephron.ren |
无 |
P0 |
| H-006 |
导航→提示词 |
点击「提示词」 |
跳转 prompt.ephron.ren |
无 |
P0 |
| H-007 |
登录链接 |
未登录时点击「未登录」 |
跳转 auth.ephron.ren/login |
无 |
P0 |
| H-008 |
登出链接 |
已登录时点击用户名 |
显示登出选项 |
任意 |
P1 |
| H-009 |
个人信息 |
检查 hero 区域 |
显示姓名、技能标签 |
无 |
P1 |
| H-010 |
联系按钮 |
点击「联系我」 |
弹出邮箱/复制功能 |
无 |
P2 |
| H-011 |
备案链接 |
点击 ICP/公安备案 |
跳转官方网站 |
无 |
P2 |
| H-012 |
健康检查 |
访问 /health |
返回 {"status":"ok"} |
无 |
P2 |
1.2 管理后台 (/admin)
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| H-013 |
Admin 首页 |
以 Elaina_admin 访问 /admin |
显示内容编辑器,含草稿/发布/丢弃功能 |
管理员 |
P0 |
| H-014 |
Admin 权限拦截 |
以 Elaina_user 访问 /admin |
重定向到登录页或提示权限不足 |
普通 |
P0 |
| H-015 |
Admin 未登录 |
未登录访问 /admin |
重定向到 auth.ephron.ren/login?redirect=... |
无 |
P0 |
| H-016 |
保存草稿 |
编辑内容后 POST /admin/save |
保存成功,不影响已发布版本 |
管理员 |
P0 |
| H-016a |
结构化 JSON 内容 |
编辑 experience/projects/skills 各 section |
各 section 独立保存,含 is_draft 标记 |
管理员 |
P1 |
| H-016b |
Service Token 拒绝 |
带 Authorization: Bearer 访问 /admin |
返回 403,审计日志记录 |
服务 |
P0 |
| H-017 |
发布内容 |
POST /admin/publish |
发布成功,草稿被清除 |
管理员 |
P0 |
| H-018 |
丢弃草稿 |
POST /admin/discard |
草稿被丢弃,已发布版本不变 |
管理员 |
P1 |
| H-019 |
CSRF 保护 |
不带 csrf_token 提交表单 |
返回「CSRF token 验证失败」 |
管理员 |
P0 |
| H-020 |
速率限制 |
1 分钟内保存 21+ 次 |
第 21 次返回 429 |
管理员 |
P1 |
| H-021 |
Service Token 拦截 |
带 Authorization: Bearer *** 访问 /admin |
返回 403 |
服务 |
P1 |
| H-022 |
登出 |
POST /admin/logout |
Cookie 清除,跳转首页 |
管理员 |
P0 |
模块 2:Auth 认证服务 (auth.ephron.ren)
2.1 登录页面
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| A-001 |
登录页加载 |
访问 /login |
200,显示用户名/密码表单 |
无 |
P0 |
| A-002 |
空表单提交 |
不填写直接登录 |
浏览器原生验证拦截 |
无 |
P0 |
| A-003 |
错误凭证 |
输入 wrong/wrong |
显示错误消息,不跳转 |
无 |
P0 |
| A-004 |
管理员登录 |
Elaina_admin / Elaina2026! |
登录成功,设置 Cookie |
管理员 |
P0 |
| A-005 |
普通用户登录 |
Elaina_user / Elaina2026! |
登录成功,设置 Cookie |
普通 |
P0 |
| A-006 |
登录后跳转 |
带 redirect 参数登录 |
跳转到指定 URL |
任意 |
P0 |
| A-007 |
登录成功页 |
不带 redirect 登录 |
跳转到 /login-success |
任意 |
P1 |
| A-008 |
登录限流 |
1 分钟内 6 次错误 |
第 6 次 429 |
无 |
P1 |
| A-009 |
注册链接 |
点击「立即注册」 |
跳转 /register |
无 |
P0 |
| A-010 |
提示消息 |
带 message 参数访问 |
显示提示文字 |
无 |
P1 |
2.2 注册页面
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| A-011 |
注册页加载 |
访问 /register |
200,显示注册表单 |
无 |
P0 |
| A-012 |
表单字段 |
检查所有字段 |
用户名/密码/确认密码/邀请码/邮箱(可选) |
无 |
P0 |
| A-013 |
空表单提交 |
不填写直接注册 |
验证拦截 |
无 |
P0 |
| A-014 |
密码不一致 |
输入不同密码 |
显示「两次输入的密码不一致」 |
无 |
P0 |
| A-015 |
弱密码 |
输入 12345678 |
显示密码强度不足 |
无 |
P0 |
| A-015a |
弱密码黑名单 |
输入常见弱密码 (password/abc123/qwerty 等) |
拒绝,提示密码过于常见 |
无 |
P0 |
| A-015b |
密码复杂度 |
输入仅数字 12345678 / 仅小写 abcdefgh |
拒绝,需满足 3/4 类别(大小写+数字+特殊字符) |
无 |
P0 |
| A-015c |
密码长度下限 |
输入 7 位强混合密码 |
拒绝,最少 8 字符 |
无 |
P0 |
| A-015d |
密码长度上限 |
输入 200 位密码 |
拒绝,最多 128 字符 |
无 |
P1 |
| A-016 |
无效邀请码 |
输入错误邀请码 |
显示「邀请码无效」 |
无 |
P0 |
| A-017 |
正常注册 |
使用 7CQ0-GE9S-L6QS |
注册成功,自动登录 |
无 |
P0 |
| A-017a |
注册自动登录 |
注册成功后检查 Cookie |
自动设置 ephron_auth Cookie,无需再次登录 |
无 |
P0 |
| A-017b |
邀请码过期 |
使用已过期的邀请码注册 |
显示「邀请码已过期」 |
无 |
P0 |
| A-017c |
邀请码用尽 |
使用已达最大使用次数的邀请码 |
显示「邀请码已失效」 |
无 |
P0 |
| A-018 |
用户名重复 |
使用已存在的用户名 |
显示「用户名已被使用」 |
无 |
P0 |
| A-018a |
用户名黑名单 |
注册保留名 (admin/root/system/ephron 等) |
拒绝,提示用户名不可用 |
无 |
P0 |
| A-018b |
用户名格式 |
输入 1abc(数字开头)/ ab(过短)/ 含特殊字符 |
验证拦截:3-20 字符,字母开头,仅字母数字下划线 |
无 |
P0 |
| A-018c |
邮箱格式验证 |
输入 invalid / a@ / @b.c |
邮箱格式错误提示 |
无 |
P1 |
| A-018d |
邮箱唯一性 |
使用已注册的邮箱 |
显示「邮箱已被使用」 |
无 |
P1 |
| A-019 |
用户名可用性检查 |
GET /api/check-username?username=xxx |
返回 {available: true/false} |
无 |
P1 |
| A-019a |
用户名检查限流 |
1 分钟内 21+ 次请求 |
第 21 次 429 |
无 |
P1 |
| A-020 |
邀请码验证 |
POST /api/verify-invite |
返回 {valid: true/false} |
无 |
P1 |
| A-020a |
邀请码验证限流 |
1 分钟内 11+ 次请求 |
第 11 次 429 |
无 |
P1 |
| A-020b |
注册限流 |
1 小时内 6 次注册 |
第 6 次 429 |
无 |
P1 |
2.3 登出与跨服务认证
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| A-021 |
Auth 登出 |
POST /api/logout |
Cookie 清除,跳转 /login |
任意 |
P0 |
| A-022 |
Blog 登出 |
访问 blog.ephron.ren/logout |
Cookie 清除 |
任意 |
P0 |
| A-023 |
Canvas 登出 |
访问 canvas.ephron.ren/logout |
Cookie 清除 |
任意 |
P0 |
| A-024 |
Prompt 登出 |
访问 prompt.ephron.ren/logout |
Cookie 清除 |
任意 |
P0 |
| A-025 |
Home 登出 |
访问 www.ephron.ren/logout |
Cookie 清除 |
任意 |
P0 |
| A-026 |
跨服务 Cookie |
Auth 登录后访问 Blog |
Blog 显示已登录态 |
任意 |
P0 |
| A-027 |
跨服务 Cookie |
Auth 登录后访问 Canvas |
Canvas 显示已登录态 |
任意 |
P0 |
| A-028 |
跨服务 Cookie |
Auth 登录后访问 Prompt |
Prompt 显示已登录态 |
任意 |
P0 |
| A-029 |
API 验证(已登录) |
GET /api/auth/verify |
200 {authenticated: true} |
任意 |
P0 |
| A-029a |
API 验证 min_role |
GET /api/auth/verify?min_role=admin |
普通用户返回 403,管理员返回 200 |
任意 |
P0 |
| A-029b |
服务管理员认证 |
GET /api/authz/service-admin |
管理员返回 200,普通用户返回 403 |
任意 |
P1 |
| A-030 |
API 验证(未登录) |
GET /api/auth/verify |
401 |
无 |
P0 |
2.4 管理后台 — 总览 (/admin)
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| A-031 |
Admin 首页 |
以管理员访问 /admin |
显示统计面板(活跃用户数、邀请码数、近 7 天注册等) |
管理员 |
P0 |
| A-031a |
统计数据准确性 |
对比 Admin 面板数据与数据库 |
活跃用户数/邀请码数/近 7 天注册数准确 |
管理员 |
P1 |
| A-032 |
Admin 权限拦截 |
以普通用户访问 /admin |
重定向或权限不足提示 |
普通 |
P0 |
| A-033 |
Admin 未登录 |
未登录访问 /admin |
重定向到 /login?redirect=/admin |
无 |
P0 |
2.5 管理后台 — 邀请码管理 (/admin/invites)
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| A-034 |
邀请码列表 |
访问 /admin/invites |
显示所有邀请码,含状态、使用次数、过期时间 |
管理员 |
P0 |
| A-035 |
生成邀请码 |
填写最大使用次数/过期天数/备注,提交 |
生成新邀请码,显示在列表 |
管理员 |
P0 |
| A-036 |
禁用邀请码 |
点击禁用按钮 |
状态变为禁用 |
管理员 |
P0 |
| A-037 |
启用邀请码 |
点击启用按钮 |
状态恢复启用 |
管理员 |
P0 |
| A-038 |
删除邀请码 |
点击删除按钮 |
邀请码及使用记录被删除 |
管理员 |
P1 |
| A-038a |
删除邀请码级联 |
删除有使用记录的邀请码 |
使用记录同步删除,无孤立数据 |
管理员 |
P1 |
| A-039 |
CSRF 保护 |
不带 csrf_token 提交 |
返回验证失败 |
管理员 |
P0 |
| A-040 |
限流 |
1 分钟内生成 11+ 个 |
第 11 个 429 |
管理员 |
P1 |
2.6 管理后台 — 用户管理 (/admin/users)
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| A-041 |
活跃用户列表 |
访问 /admin/users |
显示所有活跃用户 |
管理员 |
P0 |
| A-042 |
已禁用用户列表 |
访问 /admin/users/disabled |
显示已禁用用户 |
管理员 |
P0 |
| A-043 |
禁用用户 |
选择用户,点击禁用 |
用户状态变为禁用 |
管理员 |
P0 |
| A-044 |
禁用自己 |
尝试禁用自己的账号 |
返回「不能禁用自己」 |
管理员 |
P0 |
| A-045 |
启用用户 |
选择已禁用用户,点击启用 |
用户恢复活跃 |
管理员 |
P0 |
| A-046 |
删除用户 |
选择已禁用用户,点击删除 |
用户被永久删除 |
管理员 |
P1 |
| A-046a |
删除用户级联 |
删除有角色/登录日志/邀请码记录的用户 |
角色关联、登录日志、邀请码使用记录同步删除 |
管理员 |
P1 |
| A-046b |
删除活跃用户 |
尝试删除未禁用的用户 |
拒绝,需先禁用再删除 |
管理员 |
P1 |
| A-047 |
用户详情 |
点击用户名 /admin/users/{username} |
显示用户详情和角色编辑 |
管理员 |
P0 |
| A-047a |
用户详情角色编辑 |
在详情页修改用户角色 |
角色更新成功,页面刷新后反映新角色 |
管理员 |
P0 |
2.7 管理后台 — 角色权限管理 (/admin/roles)
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| A-048 |
角色列表 |
访问 /admin/roles |
显示所有角色及权限 |
管理员 |
P0 |
| A-049 |
创建角色 |
填写 key/name/description/权限,提交 |
创建成功 |
管理员 |
P0 |
| A-050 |
删除角色 |
删除自定义角色 |
删除成功(内置角色不可删) |
管理员 |
P1 |
| A-051 |
分配角色 |
POST /admin/users/roles/assign |
角色绑定成功 |
管理员 |
P0 |
| A-052 |
移除角色 |
POST /admin/users/roles/remove |
角色移除成功 |
管理员 |
P0 |
| A-053 |
批量更新角色 |
POST /admin/users/roles/update |
用户角色更新 |
管理员 |
P1 |
| A-054 |
角色权限不足 |
普通用户访问 /admin/roles |
重定向或提示权限不足 |
普通 |
P0 |
2.8 管理后台 — 审计日志 (/admin/audit)
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| A-055 |
审计日志页 |
访问 /admin/audit |
显示操作日志列表 |
管理员 |
P0 |
| A-056 |
筛选功能 |
按 actor_id/service/action/time 筛选 |
返回过滤结果 |
管理员 |
P1 |
| A-057 |
时间范围 |
设置 start_time/end_time |
返回该时段日志 |
管理员 |
P1 |
| A-058 |
权限控制 |
普通用户访问 |
重定向或提示权限不足 |
普通 |
P0 |
2.9 管理后台 — 服务账号 (/admin/service-accounts)
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| A-059 |
服务账号列表 |
访问 /admin/service-accounts |
显示所有服务账号 |
管理员 |
P0 |
| A-060 |
创建服务账号 |
填写名称/描述,提交 |
创建成功,自动生成 key |
管理员 |
P0 |
| A-061 |
生成令牌 |
POST /admin/service-accounts/tokens/generate |
生成 token,显示一次 |
管理员 |
P0 |
| A-062 |
吊销令牌 |
吊销已有 token |
Token 失效 |
管理员 |
P1 |
| A-063 |
停用服务账号 |
停用服务账号 |
账号不可用 |
管理员 |
P1 |
| A-064 |
权限控制 |
普通用户访问 |
重定向或提示权限不足 |
普通 |
P0 |
模块 3:Blog 博客服务 (blog.ephron.ren)
3.1 公开页面
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| B-001 |
博客首页 |
访问 / |
200,显示最新文章 + 统计 |
无 |
P0 |
| B-002 |
文章列表 |
访问 /posts |
显示所有已发布文章 |
无 |
P0 |
| B-003 |
文章详情 |
点击文章 /posts/{slug} |
Markdown 正确渲染,显示阅读时间、浏览量 |
无 |
P0 |
| B-003a |
阅读时间估算 |
查看中文/英文文章 |
中文 300 字/分钟,英文 200 词/分钟计算 |
无 |
P2 |
| B-003b |
浏览量计数 |
刷新文章详情页 |
浏览量递增(数据库记录) |
无 |
P2 |
| B-003c |
CRLF→LF 规范化 |
提交含 CRLF 的文章内容 |
保存后内容为 LF 换行 |
管理员 |
P2 |
| B-004 |
代码高亮 |
查看含代码块的文章 |
语法高亮正常 |
无 |
P1 |
| B-005 |
数学公式 |
查看含 LaTeX 的文章 |
MathJax 渲染正常 |
无 |
P1 |
| B-006 |
归档页 |
访问 /archive |
按年月分组显示 |
无 |
P1 |
| B-007 |
标签列表 |
访问 /tags |
显示标签及数量 |
无 |
P1 |
| B-008 |
按标签筛选 |
点击标签 /tags/{tag} |
显示该标签文章 |
无 |
P1 |
| B-009 |
RSS Feed |
访问 /feed |
有效 RSS XML |
无 |
P1 |
| B-010 |
Sitemap |
访问 /sitemap.xml |
有效 Sitemap XML |
无 |
P2 |
| B-011 |
草稿不可见 |
未登录访问草稿 URL |
404 |
无 |
P0 |
| B-011a |
草稿预览(已登录) |
管理员访问草稿 URL |
正常显示,含草稿标记 |
管理员 |
P0 |
| B-012 |
草稿可见 |
管理员访问草稿 URL |
正常显示 |
管理员 |
P0 |
| B-013 |
404 页面 |
访问 /posts/not-exist |
404 |
无 |
P1 |
3.2 搜索
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| B-014 |
简单搜索 |
/posts?q=关键词 |
返回匹配文章 |
无 |
P0 |
| B-015 |
全文搜索 |
/posts?q=关键词&mode=fulltext |
返回匹配文章 + 高亮 |
无 |
P1 |
| B-015a |
全文搜索中文分词 |
/posts?q=关键词&mode=fulltext(中文关键词) |
jieba 分词正确,返回相关结果 |
无 |
P1 |
| B-015b |
搜索结果高亮 |
查看 fulltext 搜索结果 |
匹配关键词高亮显示,HTML 标签已转义 |
无 |
P1 |
| B-015c |
搜索模式对比 |
同一关键词分别用 simple 和 fulltext |
simple 为字符串匹配,fulltext 为 BM25 排序 |
无 |
P2 |
| B-016 |
空搜索 |
/posts?q= |
显示所有文章 |
无 |
P1 |
| B-017 |
无结果 |
搜索不存在的词 |
空结果或提示 |
无 |
P1 |
3.3 评论系统
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| B-018 |
评论显示 |
查看文章底部 |
显示已审核评论 |
无 |
P0 |
| B-019 |
提交评论(已登录) |
POST /api/comments/ |
成功,提示等待审核 |
任意 |
P0 |
| B-020 |
提交评论(未登录) |
POST /api/comments/ |
401 |
无 |
P0 |
| B-021 |
回复评论 |
带 parent_id 提交 |
创建嵌套回复 |
任意 |
P2 |
| B-022 |
评论限流 |
1 分钟内 6+ 条 |
第 6 条 429 |
任意 |
P1 |
3.4 点赞系统
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| B-023 |
点赞状态 |
GET /api/likes/posts/{slug} |
返回 liked + like_count |
无 |
P0 |
| B-024 |
点赞 |
POST /api/likes/toggle |
点赞数 +1 |
无 |
P0 |
| B-025 |
取消点赞 |
再次 toggle |
点赞数 -1 |
无 |
P0 |
| B-025a |
点赞统计 API |
GET /api/likes/stats |
返回所有文章点赞统计 |
无 |
P2 |
| B-026 |
点赞限流 |
1 分钟内 11+ 次 |
第 11 次 429 |
无 |
P2 |
3.5 管理后台 (/admin)
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| B-027 |
Admin 首页 |
以管理员访问 /admin |
文章列表(含草稿)+ 统计 |
管理员 |
P0 |
| B-028 |
搜索文章 |
在 Admin 搜索框输入关键词 |
显示匹配结果 |
管理员 |
P1 |
| B-029 |
新建文章 |
/admin/new,填标题/内容/标签,提交 |
创建成功 |
管理员 |
P0 |
| B-030 |
编辑文章 |
/admin/edit/{slug},修改后保存 |
保存成功 |
管理员 |
P0 |
| B-031 |
删除文章 |
点击删除 |
文章删除 |
管理员 |
P0 |
| B-032 |
切换草稿 |
点击草稿/发布切换 |
状态切换 |
管理员 |
P0 |
| B-033 |
切换置顶 |
点击置顶切换 |
置顶状态切换 |
管理员 |
P1 |
| B-033a |
置顶文章排序 |
置顶文章在列表中 |
置顶文章排在非置顶之前 |
管理员 |
P1 |
| B-034 |
图片上传 |
上传 jpg/png/gif/webp |
成功,返回 URL + Markdown 片段 |
管理员 |
P1 |
| B-034a |
图片自动转 WebP |
上传 jpg/png 图片 |
自动转换为 WebP 格式,最大 1920x1080 |
管理员 |
P1 |
| B-034b |
图片上传返回格式 |
检查上传响应 |
返回 URL、Markdown 片段、文件名、大小、尺寸 |
管理员 |
P2 |
| B-035 |
图片大小限制 |
上传 >5MB 图片 |
返回错误 |
管理员 |
P1 |
| B-036 |
内容大小限制 |
提交 >1MB 内容 |
返回错误 |
管理员 |
P1 |
| B-037 |
CSRF 保护 |
不带 csrf_token 提交 |
验证失败 |
管理员 |
P0 |
| B-038 |
创建限流 |
1 分钟内创建 11+ 篇 |
第 11 篇 429 |
管理员 |
P1 |
| B-039 |
保存限流 |
1 分钟内保存 21+ 次 |
第 21 次 429 |
管理员 |
P1 |
| B-040 |
删除限流 |
1 分钟内删除 6+ 篇 |
第 6 篇 429 |
管理员 |
P1 |
| B-041 |
Admin 权限拦截 |
普通用户访问 /admin |
重定向或权限不足 |
普通 |
P0 |
| B-042 |
Admin 登出 |
POST /admin/logout |
Cookie 清除 |
管理员 |
P0 |
3.6 评论管理后台
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| B-043a |
评论管理页面 |
访问 /admin/comments |
显示评论管理 UI(审核/删除操作) |
管理员 |
P0 |
| B-043b |
评论分页 |
评论超过单页时 |
分页控件正常 |
管理员 |
P1 |
3.6.1 评论管理 API
| 编号 | 测试内容 | 步骤 | 预期 | 账号 | 优先级 |
| B-043 | 全部评论 | GET /api/comments/admin/all | 返回评论列表(含未审核) | 管理员 | P0 |
| B-044 | 待审核评论 | GET /api/comments/admin/pending | 返回待审核列表 | 管理员 | P0 |
| B-045 | 审核通过 | POST /api/comments/admin/{id}/approve | 评论变为已审核 | 管理员 | P0 |
| B-046 | 删除评论 | DELETE /api/comments/admin/{id} | 评论被删除 | 管理员 | P0 |
| B-047 | 评论详情 | GET /api/comments/admin/{id} | 返回含 IP 等敏感信息 | 管理员 | P1 |
| B-048 | 权限拦截 | 普通用户访问 admin API | 403 | 普通 | P0 |
3.7 Service API
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| B-049 |
列表草稿 |
GET /api/service/posts |
可管理的草稿列表 |
服务 |
P1 |
| B-049a |
所有权隔离 |
服务 A 创建的草稿,服务 B 尝试访问 |
403 或 404 |
服务 |
P0 |
| B-049b |
人工接管 |
服务创建的草稿,管理员编辑 |
编辑成功,ownership_type 保持 service |
管理员 |
P1 |
| B-050 |
创建草稿 |
POST /api/service/posts |
成功,返回 slug |
服务 |
P1 |
| B-051 |
更新草稿 |
PATCH /api/service/posts/{slug} |
成功 |
服务 |
P1 |
| B-052 |
删除草稿 |
DELETE /api/service/posts/{slug} |
成功 |
服务 |
P1 |
| B-053 |
无 token |
不带 Authorization |
401 |
无 |
P1 |
| B-054 |
非拥有者 |
访问他人草稿 |
403 |
服务 |
P1 |
模块 4:Canvas 画布服务 (canvas.ephron.ren)
4.1 公开页面
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| C-001 |
首页加载 |
访问 / |
200,显示 Canvas 列表 |
无 |
P0 |
| C-002 |
分类筛选 |
点击分类标签 |
按分类显示 |
无 |
P1 |
| C-003 |
搜索 |
输入关键词 |
返回匹配结果 |
无 |
P1 |
| C-004 |
预览页 |
访问 /view/{slug} |
iframe 加载 Canvas 内容 |
无 |
P0 |
| C-005 |
原始 HTML |
访问 /raw/{slug} |
返回原始 HTML |
无 |
P0 |
| C-005a |
原始 HTML 安全 |
/raw/{slug} 响应头检查 |
Content-Type 为 text/html,有 CSP 限制 |
无 |
P0 |
| C-006 |
访问计数 |
POST /api/view/{slug} |
计数递增(AJAX 请求) |
无 |
P1 |
| C-007 |
草稿不可见 |
未登录访问草稿 |
404 |
无 |
P0 |
| C-008 |
空状态 |
无 Canvas 时 |
显示「还没有工具」 |
无 |
P1 |
4.2 管理后台 (/admin)
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| C-009 |
Admin 首页 |
以管理员访问 /admin |
显示所有 Canvas(含草稿)+ 统计 |
管理员 |
P0 |
| C-010 |
搜索 |
在 Admin 搜索 |
显示匹配结果 |
管理员 |
P1 |
| C-011 |
新建 Canvas |
/admin/new,填标题/slug/内容/分类,提交 |
创建成功 |
管理员 |
P0 |
| C-011a |
用户指定 slug |
创建时自定义 slug |
slug 保存成功,可通过自定义 slug 访问 |
管理员 |
P1 |
| C-011b |
slug 格式验证 |
输入大写/特殊字符/中文 slug |
拒绝,仅允许小写字母数字下划线连字符 |
管理员 |
P0 |
| C-011c |
分类/来源字段 |
选择预定义分类和来源 |
正确保存并显示 |
管理员 |
P1 |
| C-012 |
编辑 Canvas |
/admin/edit/{slug},修改后保存 |
保存成功 |
管理员 |
P0 |
| C-013 |
删除 Canvas |
POST /admin/delete |
删除成功 |
管理员 |
P0 |
| C-014 |
切换草稿 |
POST /admin/toggle-draft |
状态切换 |
管理员 |
P0 |
| C-015 |
CSRF 保护 |
不带 csrf_token 提交 |
验证失败 |
管理员 |
P0 |
| C-016 |
创建限流 |
1 分钟内 11+ 个 |
第 11 个 429 |
管理员 |
P1 |
| C-017 |
保存限流 |
1 分钟内 21+ 次 |
第 21 次 429 |
管理员 |
P1 |
| C-018 |
权限拦截 |
普通用户访问 /admin |
重定向或权限不足 |
普通 |
P0 |
| C-019 |
登出 |
POST /admin/logout |
Cookie 清除 |
管理员 |
P0 |
4.3 Service API
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| C-020 |
列表草稿 |
GET /api/service/canvas |
可管理的草稿列表 |
服务 |
P1 |
| C-020a |
所有权隔离 |
服务 A 创建的草稿,服务 B 尝试访问 |
403 或 404 |
服务 |
P0 |
| C-021 |
创建草稿 |
POST /api/service/canvas |
成功,返回 slug |
服务 |
P1 |
| C-022 |
更新草稿 |
PATCH /api/service/canvas/{slug} |
成功 |
服务 |
P1 |
| C-023 |
删除草稿 |
DELETE /api/service/canvas/{slug} |
成功 |
服务 |
P1 |
| C-024 |
无 token |
不带 Authorization |
401 |
无 |
P1 |
模块 5:Prompt 提示词服务 (prompt.ephron.ren)
5.1 公开页面
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| P-001 |
首页加载 |
访问 / |
200,显示提示词列表 |
无 |
P0 |
| P-002 |
搜索 |
/?q=关键词 |
返回匹配结果 |
无 |
P1 |
| P-003 |
分类筛选 |
/?category=写作 |
按分类显示 |
无 |
P1 |
| P-004 |
标签筛选 |
/?tag=xxx |
按标签显示 |
无 |
P1 |
| P-005 |
统计信息 |
检查页面 |
显示总数/模板数/分类数 |
无 |
P2 |
| P-006 |
详情页 |
访问 /prompts/{key} |
显示标题/内容/描述/标签 |
无 |
P0 |
| P-006a |
Public JSON API |
GET /api/prompts/{key} |
返回 JSON 格式提示词(无需登录) |
无 |
P0 |
| P-006b |
Public API 列表 |
GET /api/prompts?limit=10&offset=0 |
返回分页提示词列表 |
无 |
P1 |
| P-006c |
Public API 版本 |
GET /api/prompts/{key}?version=2 |
返回指定版本内容 |
无 |
P1 |
| P-006d |
API 草稿拦截 |
GET /api/prompts/{key}(该 key 为草稿) |
返回 400 或 404 |
无 |
P0 |
| P-007 |
草稿不可见 |
未登录访问草稿 |
404 |
无 |
P0 |
| P-008 |
404 页面 |
访问 /prompts/not-exist |
404 |
无 |
P1 |
5.2 管理后台 (/admin)
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| P-009 |
Admin 首页 |
以管理员访问 /admin |
显示所有提示词(含草稿) |
管理员 |
P0 |
| P-010 |
搜索/筛选 |
在 Admin 搜索/按分类/按标签 |
返回匹配结果 |
管理员 |
P1 |
| P-011 |
新建提示词 |
/admin/new,填标题/内容/分类/标签/描述,提交 |
创建成功 |
管理员 |
P0 |
| P-012 |
模板标记 |
创建时勾选「是模板」 |
is_template 正确保存 |
管理员 |
P1 |
| P-012a |
模板变量 |
创建模板提示词,填写 variables(CSV 格式) |
变量保存成功 |
管理员 |
P1 |
| P-012b |
示例输入/输出 |
填写 example_input 和 example_output |
保存成功,详情页显示 |
管理员 |
P2 |
| P-012c |
推荐模型 |
填写 recommended_model 字段 |
保存成功,详情页显示 |
管理员 |
P2 |
| P-013 |
编辑提示词 |
/admin/edit/{key},修改后保存 |
保存成功 |
管理员 |
P0 |
| P-014 |
删除提示词 |
POST /admin/delete/{key} |
删除成功 |
管理员 |
P0 |
| P-015 |
切换草稿 |
POST /admin/toggle/{key} |
状态切换 |
管理员 |
P0 |
| P-016 |
版本管理 |
访问 /admin/versions/{key} |
显示版本历史 |
管理员 |
P1 |
| P-017 |
切换版本 |
POST /admin/set-version/{key} |
切换到指定版本 |
管理员 |
P1 |
| P-017a |
版本切换后 API |
切换版本后 GET /api/prompts/{key} |
返回新切换的版本内容 |
管理员 |
P1 |
| P-018 |
CSRF 保护 |
不带 csrf_token 提交 |
验证失败 |
管理员 |
P0 |
| P-019 |
创建限流 |
1 分钟内 11+ 个 |
第 11 个 429 |
管理员 |
P1 |
| P-020 |
保存限流 |
1 分钟内 21+ 次 |
第 21 次 429 |
管理员 |
P1 |
| P-021 |
权限拦截 |
普通用户访问 /admin |
重定向或权限不足 |
普通 |
P0 |
| P-022 |
登出 |
GET /logout |
Cookie 清除 |
任意 |
P0 |
5.3 Service API
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| P-023 |
列表草稿 |
GET /api/service/prompts |
可管理的草稿列表 |
服务 |
P1 |
| P-023a |
所有权隔离 |
服务 A 创建的草稿,服务 B 尝试访问 |
403 或 404 |
服务 |
P0 |
| P-024 |
创建草稿 |
POST /api/service/prompts |
成功 |
服务 |
P1 |
| P-025 |
更新草稿 |
PATCH /api/service/prompts/{key} |
成功 |
服务 |
P1 |
| P-026 |
删除草稿 |
DELETE /api/service/prompts/{key} |
成功 |
服务 |
P1 |
| P-027 |
无 token |
不带 Authorization |
401 |
无 |
P1 |
模块 6:安全与一致性
6.1 安全头
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| S-001 |
X-Content-Type-Options |
检查响应头 |
nosniff |
P1 |
| S-002 |
X-Frame-Options |
检查响应头 |
DENY |
P1 |
| S-003 |
Referrer-Policy |
检查响应头 |
strict-origin-when-cross-origin |
P1 |
| S-004 |
CSP |
检查 Content-Security-Policy |
存在且合理 |
P1 |
| S-004a |
CSP script-src |
检查 script-src 策略 |
仅 self + unsafe-inline,无 unsafe-eval |
P1 |
| S-004b |
CSP form-action |
检查 form-action |
仅 self |
P1 |
| S-004c |
CSP frame-ancestors |
检查 frame-ancestors |
none(防 clickjacking) |
P1 |
6.2 一致性检查
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| S-005 |
mobile.css 引入 |
检查各页面 HTML |
所有页面一致引入或不引入 |
P1 |
| S-006 |
loader.js 引入 |
检查各页面 HTML |
所有页面一致引入 |
P1 |
| S-007 |
DOCTYPE 前无多余内容 |
检查各页面源码第一字节 |
无 BOM/换行 |
P1 |
| S-008 |
Auth 页导航 |
访问 Auth 登录/注册页 |
有返回主页的链接 |
P1 |
| S-009 |
user-scalable |
检查 viewport meta |
无 user-scalable=no |
P1 |
| S-009a |
AJAX CSRF |
Blog/Canvas/Prompt 图片上传和评论审核 |
X-CSRF-Token header 验证通过 |
P0 |
| S-009b |
Cache-Control |
敏感页面(auth verify/service accounts) |
no-store 或 no-cache |
P1 |
6.3 控制台检查
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| S-010 |
Home 无 JS 错误 |
访问首页,检查控制台 |
无 error |
P1 |
| S-011 |
Auth 无 JS 错误 |
访问登录/注册页 |
无 error |
P1 |
| S-012 |
Blog 无 JS 错误 |
访问首页/文章详情/Admin |
无 error |
P1 |
| S-013 |
Canvas 无 JS 错误 |
访问首页/预览页/Admin |
无 error |
P1 |
| S-014 |
Prompt 无 JS 错误 |
访问首页/详情页/Admin |
无 error |
P1 |
模块 7:边界与异常输入
7.1 XSS 注入测试
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| XSS-001 |
文章标题 XSS |
Blog Admin 新建文章,标题 <script>alert('XSS')</script>,发布后访问 |
渲染为纯文本,不执行脚本 |
管理员 |
P0 |
| XSS-002 |
文章内容 XSS |
内容输入 <img src=x onerror=alert(1)> |
不执行,显示 broken image |
管理员 |
P0 |
| XSS-003 |
评论 XSS |
提交评论 <svg onload=alert(1)> |
渲染为纯文本,不执行 |
任意 |
P0 |
| XSS-004 |
Canvas 标题 XSS |
Canvas 标题输入 <script>alert(1)</script> |
不执行 |
管理员 |
P0 |
| XSS-005 |
Prompt 标题 XSS |
Prompt 标题输入 "><script>alert(1)</script> |
不执行 |
管理员 |
P0 |
| XSS-006 |
用户名 XSS |
注册时用户名 <script>alert(1)</script> |
验证拦截或转义 |
无 |
P0 |
| XSS-007 |
搜索框 XSS |
搜索框 <script>alert(1)</script> |
不执行,搜索结果安全显示 |
无 |
P0 |
| XSS-008 |
Bio/个人简介 XSS |
Admin 修改简介输入 XSS payload |
不执行 |
管理员 |
P0 |
| XSS-009 |
标签 XSS |
添加标签 <script>alert(1)</script> |
转义存储,安全显示 |
管理员 |
P0 |
| XSS-010 |
URL 参数 XSS |
访问 ?name=<script>alert(1)</script> |
不执行 |
无 |
P1 |
7.2 超长字符串输入
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| XSS-011 |
超长文章标题 |
标题输入 10000 字符 |
验证最大长度限制,或截断保存 |
管理员 |
P1 |
| XSS-012 |
超长文章内容 |
内容输入 10MB 文本 |
返回错误或限制(1MB) |
管理员 |
P0 |
| XSS-013 |
超长用户名 |
注册时用户名输入 500 字符 |
验证最大长度限制 |
无 |
P1 |
| XSS-014 |
超长评论 |
评论输入 50000 字符 |
验证长度限制 |
任意 |
P1 |
| XSS-015 |
超长搜索查询 |
搜索框输入 5000 字符 |
验证长度限制或正常处理 |
无 |
P1 |
| XSS-016 |
超长 Canvas 内容 |
Canvas 内容输入 50MB |
验证大小限制 |
管理员 |
P0 |
| XSS-017 |
超长 Prompt 内容 |
Prompt 内容输入 100000 字符 |
保存成功(无硬性限制则可) |
管理员 |
P1 |
| XSS-018 |
超长邮箱 |
邮箱字段输入 1000 字符 |
验证格式拦截 |
无 |
P1 |
7.3 特殊字符输入
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| XSS-019 |
特殊字符用户名 |
注册 `user |
name user&name user'name user"name` |
验证字符白名单拦截 |
无 |
| XSS-020 |
特殊字符标题 |
文章标题含 `/:*?"<> |
` |
验证安全处理 |
管理员 |
| XSS-021 |
Emoji 标题 |
标题输入 🎉🔥💻🚀 等多 emoji |
正常保存和显示 |
管理员 |
P1 |
| XSS-022 |
CJK 字符 |
标题/内容输入中日韩字符 日本語한국어中文 |
正常保存和显示 |
管理员 |
P1 |
| XSS-023 |
Unicode 特殊符 |
标题含零宽字符 或双向字符 |
安全处理,不破坏布局 |
管理员 |
P1 |
| XSS-024 |
特殊字符搜索 |
搜索 AND 1=1-- OR 1=1 |
安全处理,不报错 |
无 |
P1 |
| XSS-025 |
SQL 注入形搜索 |
搜索 ' OR '1'='1 '; DROP TABLE-- |
安全处理,无 SQL 错误 |
无 |
P1 |
| XSS-026 |
换行符注入 |
标题含 \n\r 换行 |
安全保存,显示正常 |
管理员 |
P1 |
7.4 空内容与边界提交
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| XSS-027 |
空标题文章 |
新建文章,标题留空 |
验证拦截「标题不能为空」 |
管理员 |
P0 |
| XSS-028 |
空内容文章 |
内容留空,填写标题 |
保存为草稿或提示内容不能为空 |
管理员 |
P0 |
| XSS-029 |
空评论提交 |
评论框留空提交 |
验证拦截 |
任意 |
P0 |
| XSS-030 |
仅空白字符 |
标题/内容仅输入空格/制表符 |
视为空内容,拦截 |
管理员 |
P1 |
| XSS-031 |
全角空格 |
标题输入全角空格 |
视为有效内容或提示输入无效 |
管理员 |
P1 |
| XSS-032 |
仅数字标题 |
标题输入 123456 |
正常保存 |
管理员 |
P1 |
| XSS-033 |
重复标题 |
创建两篇相同标题文章 |
允许或提示 slug 重复处理 |
管理员 |
P1 |
模块 8:安全性深度测试
8.1 Cookie 属性验证
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| SEC-001 |
auth cookie HttpOnly |
curl 检查 Set-Cookie: ephron_auth |
HttpOnly 标记存在 |
P0 |
| SEC-002 |
auth cookie Secure |
curl (HTTP) 检查 |
生产环境应返回 Secure(需 HTTPS) |
P0 |
| SEC-003 |
auth cookie SameSite |
检查 SameSite 属性 |
Lax 或 Strict,不为空 |
P0 |
| SEC-004 |
auth cookie Max-Age |
检查 Max-Age 或 Expires |
有合理过期时间(≤30天) |
P1 |
| SEC-005 |
auth cookie Domain |
检查 Domain 域 |
.ephron.ren 以便跨子域共享 |
P0 |
| SEC-006 |
CSRF cookie HttpOnly |
检查 ephron_csrf cookie |
HttpOnly=false(JS 需读取,双提交) |
P1 |
| SEC-007 |
Cookie 刷新 |
登录后等 5 分钟再次访问 |
Session 保持,cookie 未过期 |
任意 |
| SEC-008 |
跨域 Cookie 写入 |
从 blog.ephron.ren 访问 auth.ephron.ren |
auth cookie 不被 JS 读取 |
P1 |
8.2 Open Redirect 深度测试
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| SEC-009 |
redirect 到外域 |
auth.ephron.ren/login?redirect=https://evil.com |
拒绝或重定向到安全页 |
P0 |
| SEC-010 |
redirect 协议相对 |
auth.ephron.ren/login?redirect=//evil.com |
拒绝,视为相对路径处理或拒绝 |
P0 |
| SEC-011 |
redirect 协议注入 |
auth.ephron.ren/login?redirect=javascript:alert(1) |
拒绝 |
P0 |
| SEC-012 |
redirect 路径遍历 |
auth.ephron.ren/login?redirect=/..//evil.com |
拒绝或规范化处理 |
P1 |
| SEC-013 |
redirect 到子域 |
auth.ephron.ren/login?redirect=https://blog.ephron.ren |
允许(ephron.ren 子域) |
P0 |
| SEC-014 |
redirect 空值 |
auth.ephron.ren/login?redirect= |
使用默认页 |
P1 |
| SEC-015 |
redirect URL 编码 |
auth.ephron.ren/login?redirect=%2F%2Fevil.com |
拒绝或解码后拒绝 |
P1 |
| SEC-016 |
登出后 redirect |
登出时带 redirect 参数 |
拒绝到外部 URL |
P1 |
8.3 CSRF Token 深度测试
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| SEC-017 |
Token 重放 |
获取 token 后在同一 session 重复使用 |
允许(在有效期内) |
P1 |
| SEC-018 |
Token 过期 |
获取 token,等 61 分钟后再使用 |
拒绝,返回 CSRF 验证失败 |
P0 |
| SEC-019 |
Token 伪造 |
表单中填入假 token {timestamp}:fakehex |
拒绝,HMAC 验证不通过 |
P0 |
| SEC-020 |
Token 格式错误 |
表单 token 与 cookie 不一致 |
拒绝 |
P0 |
| SEC-021 |
Token 仅 cookie 无表单 |
不在表单中传 token,仅 cookie |
拒绝(双提交需两者匹配) |
P0 |
| SEC-022 |
Token 仅表单无 cookie |
传表单 token 但不带 CSRF cookie |
拒绝 |
P0 |
| SEC-023 |
Token 不同服务 |
用 blog 的 token 提交到 auth 的表单 |
拒绝(各服务 token 独立) |
P1 |
| SEC-024 |
修改 token 时钟偏倚 |
手动调整请求时间戳到未来/过去 |
过期 token 拒绝 |
P1 |
8.5 Service Account Token 认证
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| SEC-033 |
Bearer Token 认证 |
用有效 service token 请求 /api/service/* |
200,返回数据 |
P0 |
| SEC-034 |
Token SHA256 查找 |
数据库中 token 为 SHA256 哈希 |
明文 token 不存储 |
P0 |
| SEC-035 |
Token 使用追踪 |
使用 token 后检查 last_used_at/ip/ua |
记录更新 |
P1 |
| SEC-036 |
Token 过期 |
使用带 expires_at 的过期 token |
401 |
P0 |
| SEC-037 |
吊销 Token |
吊销后使用旧 token |
401 |
P0 |
| SEC-038 |
Token 跨服务权限 |
Blog service token 访问 Canvas API |
403(各服务独立) |
P0 |
8.4 路径遍历与文件安全
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| SEC-025 |
文章 slug 路径遍历 |
访问 /posts/../../../etc/passwd |
404 或安全拒绝 |
P0 |
| SEC-026 |
Canvas slug 路径遍历 |
访问 /view/../../secret.txt |
404 |
P0 |
| SEC-027 |
Prompt key 路径遍历 |
访问 /prompts/../../config.py |
404 |
P0 |
| SEC-028 |
管理接口越权 |
普通用户直接 POST 到 admin 接口 |
403 |
普通 |
| SEC-029 |
直接访问管理 API |
curl 绕过 UI 访问 /admin/api/... |
RBAC 拦截 |
普通 |
| SEC-030 |
文件上传绕过扩展名 |
上传 shell.php.jpg |
应拒绝(只允许图片类型) |
管理员 |
| SEC-031 |
文件上传 MIME 类型绕过 |
POST 修改 Content-Type 但内容是 HTML |
验证文件内容而非仅 MIME |
管理员 |
| SEC-032 |
文件名 XSS |
上传含 <script> 文件名的图片 |
存储时清理文件名 |
管理员 |
模块 9:会话管理
9.1 Token 生命周期
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| SES-001 |
Token 过期跳转 |
等待 token 过期后访问受保护页 |
重定向到 login 页 |
任意 |
| SES-002 |
Token 过期 API |
用过期 token 请求 API |
401 {"error": "token expired"} |
任意 |
| SES-003 |
角色降级权限刷新 |
管理员登录后 DB 改为 user,刷新页面 |
页面应反映新权限(读取 DB 角色) |
管理员 |
| SES-004 |
角色升级权限刷新 |
user 登录后 DB 改为 admin,刷新 |
需重新登录才生效(session 不自动刷新) |
普通 |
| SES-005 |
用户禁用后会话 |
用户登录后 DB 禁用账号,已存 cookie 访问 |
拒绝访问或立即登出 |
任意 |
| SES-006 |
多设备登录 |
同时两台设备用同一账号 |
两 session 均有效,或强制下线 |
任意 |
| SES-007 |
登录成功 token 刷新 |
登录后检查是否有新 session 产生 |
每次登录产生新 token |
任意 |
9.2 并发会话安全
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| SES-008 |
并发编辑草稿 |
两浏览器同时编辑同一文章并保存 |
后保存覆盖先前,或加锁提示冲突 |
管理员 |
| SES-009 |
并发评论 |
多用户同时对同一文章提交评论 |
均成功存储,时间戳不同 |
任意 |
| SES-010 |
并发点赞 |
多用户同时对同一文章 toggle 点赞 |
计数正确,无 race condition |
任意 |
| SES-011 |
Session 固定攻击 |
登录前 cookie 值 A,登录后 cookie 变为 B |
登录后 session ID 必须更换 |
任意 |
模块 10:文件上传安全
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| UPL-001 |
图片上传正常 |
上传 1MB jpg 文件 |
成功,返回 URL |
管理员 |
P0 |
| UPL-002 |
PNG 上传 |
上传 2MB png |
成功 |
管理员 |
P0 |
| UPL-003 |
WebP 上传 |
上传 webp 格式 |
成功 |
管理员 |
P0 |
| UPL-004 |
GIF 上传 |
上传 500KB gif |
成功 |
管理员 |
P0 |
| UPL-005 |
大小限制 |
上传 10MB 文件 |
返回错误「文件超过 5MB」 |
管理员 |
P0 |
| UPL-006 |
双扩展名 |
上传 shell.php.jpg |
拒绝(后端验证真实类型) |
管理员 |
P0 |
| UPL-007 |
可执行文件 |
上传 shell.exe |
拒绝,仅允许图片类型 |
管理员 |
P0 |
| UPL-008 |
恶意 SVG |
上传含 <script>alert(1)</script> 的 SVG |
拒绝或净化处理 |
管理员 |
P0 |
| UPL-009 |
polyglot 文件 |
上传既是图片又是 HTML 的文件 |
拒绝,内容检查 |
管理员 |
P0 |
| UPL-010 |
0 字节文件 |
上传 0 字节文件 |
拒绝或提示无效文件 |
管理员 |
P1 |
| UPL-011 |
超大文件名 |
上传文件名 500 字符 |
截断或正常处理 |
管理员 |
P1 |
| UPL-012 |
路径穿越文件名 |
上传 ../../../etc/passwd.jpg |
规范化文件名,安全存储 |
管理员 |
P0 |
| UPL-013 |
上传覆盖 |
上传与已有文件同名的图片 |
UUID 化命名,不覆盖 |
管理员 |
P1 |
| UPL-014 |
未登录上传 |
未登录尝试上传 |
401 重定向到登录 |
无 |
P0 |
| UPL-015 |
普通用户上传 |
普通用户尝试上传 |
403 权限不足 |
普通 |
P0 |
模块 11:搜索边界测试
| 编号 |
测试内容 |
步骤 |
预期 |
账号 |
优先级 |
| SCH-001 |
空搜索 |
/?q= 或 /?q=%20%20 |
显示所有内容 |
无 |
P1 |
| SCH-002 |
单字符搜索 |
/?q=a |
有结果或空结果提示 |
无 |
P1 |
| SCH-003 |
超长搜索 |
/?q= + 10000 字符 |
验证长度限制 |
无 |
P1 |
| SCH-004 |
SQL 注入搜索 |
/?q=' OR 1=1-- |
安全处理,显示空结果或报错 |
无 |
P0 |
| SCH-005 |
正则注入 |
/?q=(?<=.*) 特殊正则元字符 |
安全处理 |
无 |
P1 |
| SCH-006 |
搜索结果 XSS |
搜索含 <script> 内容后查看结果高亮 |
转义高亮显示 |
无 |
P0 |
| SCH-007 |
搜索跨服务 |
auth 服务搜索 /?q=blogpost |
正常处理(auth 无搜索则跳过) |
无 |
P1 |
| SCH-008 |
搜索结果分页 |
搜索结果超过单页 |
分页控件正常 |
无 |
P1 |
| SCH-009 |
搜索历史 |
输入搜索词后刷新页面 |
搜索框保留上次内容 |
无 |
P2 |
模块 12:SEO 元数据测试
12.1 Home 服务
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| SEO-001 |
首页 title |
访问 www.ephron.ren,查看 <title> |
有描述性 title,非默认 |
P1 |
| SEO-002 |
首页 meta description |
检查 <meta name="description"> |
有且长度合理(150字符左右) |
P1 |
| SEO-003 |
首页 OG 标签 |
检查 og:title, og:description, og:image, og:url |
全部存在 |
P1 |
| SEO-004 |
首页 canonical |
检查 <link rel="canonical"> |
存在,指向自身 |
P2 |
| SEO-005 |
首页 robots |
检查 robots meta 或 headers |
index, follow |
P2 |
| SEO-006 |
响应式 viewport |
检查 viewport meta |
含 width=device-width, initial-scale=1 |
P1 |
| SEO-007 |
首页 icon |
检查 favicon.ico / apple-touch-icon |
存在 |
P2 |
12.2 Blog 服务
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| SEO-008 |
文章 title |
访问文章详情页 <title> |
含文章标题 + 站点名 |
P1 |
| SEO-009 |
文章 meta description |
检查 description 内容 |
文章摘要或前 160 字符 |
P1 |
| SEO-010 |
文章 OG 标签 |
检查 og:title, og:description, og:image |
全部存在 |
P1 |
| SEO-011 |
文章 canonical |
检查 canonical URL |
存在且正确 |
P1 |
| SEO-012 |
RSS feed |
访问 /feed |
有效 XML,有 items |
P1 |
| SEO-013 |
sitemap.xml |
访问 /sitemap.xml |
有效 XML,包含所有已发布文章 |
P1 |
| SEO-014 |
文章结构化数据 |
检查 JSON-LD |
有 Article 或 BlogPosting schema |
P2 |
| SEO-015 |
归档页 title |
访问 /archive |
有描述性 title |
P2 |
| SEO-016 |
标签页 title |
访问 /tags/{tag} |
含标签名 + 站点名 |
P2 |
12.3 Canvas 服务
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| SEO-017 |
Canvas 预览页 title |
访问 /view/{slug} |
含标题 + 站点名 |
P2 |
| SEO-018 |
Canvas OG image |
检查 og:image |
存在(如有缩略图) |
P2 |
12.4 Prompt 服务
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| SEO-019 |
Prompt 详情页 title |
访问 /prompts/{key} |
含标题 + 站点名 |
P2 |
| SEO-020 |
Prompt 详情页 description |
检查 meta description |
存在 |
P2 |
12.5 robots.txt
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| SEO-021 |
robots.txt 存在 |
各子服务访问 /robots.txt |
存在内容 |
P1 |
| SEO-022 |
robots.txt 有效性 |
检查 sitemap 指令 |
指向正确的 sitemap URL |
P1 |
模块 13:无障碍(Accessibility)深度测试
13.1 键盘导航
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| A11Y-001 |
焦点可见性 |
Tab 键遍历首页 |
每个焦点元素有可见轮廓 |
P1 |
| A11Y-002 |
表单键盘操作 |
在登录表单中 Tab 切换字段,Enter 提交 |
顺序正确,Enter 提交 |
无 |
| A11Y-003 |
模态框键盘 |
打开联系弹窗后 Tab |
焦点锁定在弹窗内 |
无 |
| A11Y-004 |
下拉菜单键盘 |
使用键盘操作下拉菜单 |
上下箭头选择,Enter 确认 |
无 |
| A11Y-005 |
跳过导航 |
按 Tab 后首个链接 |
应为「跳过到主要内容」链接 |
P1 |
| A11Y-006 |
编辑器键盘操作 |
Blog Admin 编辑器,键盘操作 |
可用键盘完成基本编辑 |
管理员 |
13.2 ARIA 与语义化
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| A11Y-007 |
图片 alt |
所有 <img> 有 alt 属性 |
装饰性图片有 alt="" 或 aria-hidden |
P1 |
| A11Y-008 |
按钮语义 |
使用 <button> 而非 <div onclick> |
正确语义标签 |
P1 |
| A11Y-009 |
表单 label |
登录表单每个 input 有 <label> |
label 与 input 关联 |
P1 |
| A11Y-010 |
ARIA label |
图标按钮有 aria-label |
含义明确 |
P1 |
| A11Y-011 |
导航 landmark |
<nav> 标签存在 |
导航区有正确语义 |
P2 |
| A11Y-012 |
标题层级 |
H1/H2/H3 层级不跳过 |
逻辑清晰 |
P1 |
13.3 颜色对比度
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| A11Y-013 |
正文对比度 |
白色背景上正文文字 |
至少 4.5:1(AA 标准) |
P1 |
| A11Y-014 |
大文字对比度 |
标题文字与背景 |
至少 3:1 |
P1 |
| A11Y-015 |
链接颜色 |
正文链接颜色与正文 |
4.5:1 或有下划线 |
P1 |
| A11Y-016 |
错误提示颜色 |
红色错误文字 |
不仅依赖颜色传达信息 |
P1 |
| A11Y-017 |
按钮 hover |
按钮 hover 状态有视觉变化 |
非仅颜色变化(加下划线/边框) |
P1 |
模块 14:性能测试
14.1 页面加载
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| PERF-001 |
首页加载时间 |
访问首页,测量 TTFB |
< 1s |
P1 |
| PERF-002 |
首页完全加载 |
测量 onload 时间 |
< 3s |
P1 |
| PERF-003 |
文章详情加载 |
访问含代码块/LaTeX 的文章 |
< 3s |
P1 |
| PERF-004 |
静态资源 200 |
所有 CSS/JS/图片 |
全部 HTTP 200,无 404 |
P0 |
| PERF-005 |
外部资源 |
检查 Google Fonts / CDN 资源 |
可访问(中国大陆考虑 jsDelivr 备选) |
P1 |
| PERF-006 |
资源重复请求 |
检查同一资源是否多次请求 |
无重复请求相同资源 |
P2 |
| PERF-007 |
图片懒加载 |
博客列表页图片 |
进入视口前不加载 |
P2 |
14.2 Core Web Vitals(简化测试)
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| PERF-008 |
LCP 预估 |
首页加载后最大图片/文字渲染 |
< 2.5s |
P2 |
| PERF-009 |
CLS 检测 |
页面加载后无布局偏移 |
无意外布局移动 |
P2 |
| PERF-010 |
无长任务 |
浏览器 Performance 标签 |
无 > 50ms 的主线程阻塞 |
P2 |
14.3 首屏渲染
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| PERF-011 |
首屏无白屏 |
访问首页 |
1s 内显示内容 |
P1 |
| PERF-012 |
首屏骨架屏 |
慢网速模拟 |
有 loading 状态 |
P2 |
| PERF-013 |
内联 CSS |
检查 <head> 内联 CSS |
首屏内容立即可用 |
P2 |
模块 15:移动端交互测试
15.1 响应式布局
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| MOBILE-001 |
375px 布局 |
Chrome DevTools 设为 iPhone 12 宽度 |
无水平滚动,布局正常 |
P1 |
| MOBILE-002 |
768px 布局 |
设为 iPad 宽度 |
布局自适应 |
P1 |
| MOBILE-003 |
导航响应 |
375px 下导航栏 |
汉堡菜单或适配移动端 |
P1 |
| MOBILE-004 |
点击区域大小 |
按钮/链接触摸目标 |
≥ 44x44px |
P1 |
| MOBILE-005 |
内容溢出 |
长标题/长单词在移动端 |
自动换行,不溢出 |
P1 |
15.2 触摸交互
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| MOBILE-006 |
触摸滚动 |
触摸博客列表页 |
平滑滚动 |
无 |
| MOBILE-007 |
点击反馈 |
触摸按钮 |
有视觉反馈(ripple/高亮) |
P1 |
| MOBILE-008 |
双击缩放 |
触摸文字 |
无意外缩放(已设 viewport) |
P1 |
| MOBILE-009 |
虚拟键盘 |
移动端点击评论输入框 |
键盘弹出,页面适当上推 |
任意 |
| MOBILE-010 |
横竖屏切换 |
旋转设备方向 |
布局正常重排 |
P2 |
模块 16:跨浏览器兼容性(简化测试)
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| COMP-001 |
Flexbox 兼容性 |
检查 CSS 是否使用有前缀的 Flexbox |
无仅 Webkit 前缀的旧语法 |
P1 |
| COMP-002 |
CSS Grid 兼容性 |
检查是否用了不支持的 Grid 语法 |
提供回退方案 |
P2 |
| COMP-003 |
HTTP/2 支持 |
检查服务器 HTTP/2 |
服务器支持 HTTP/2 |
P2 |
| COMP-004 |
CORS headers |
静态资源跨域请求 |
正确 CORS 头 |
P2 |
| COMP-005 |
ES6+ 语法 |
检查 JS 是否用了现代语法 |
无仅旧浏览器支持的语法 |
P1 |
模块 17:运维与部署相关
17.1 健康检查
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| OPS-001 |
Home 健康检查 |
curl https://www.ephron.ren/health |
{"status":"ok"} |
P1 |
| OPS-002 |
Auth 健康检查 |
curl https://auth.ephron.ren/health |
{"status":"ok"} |
P1 |
| OPS-003 |
Blog 健康检查 |
curl https://blog.ephron.ren/health |
{"status":"ok"} |
P1 |
| OPS-004 |
Canvas 健康检查 |
curl https://canvas.ephron.ren/health |
{"status":"ok"} |
P1 |
| OPS-005 |
Prompt 健康检查 |
curl https://prompt.ephron.ren/health |
{"status":"ok"} |
P1 |
| OPS-006 |
健康检查无认证 |
无 cookie 访问健康检查 |
正常返回(不应需要认证) |
P1 |
17.2 错误处理
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| OPS-007 |
自定义 404 |
访问 /not-exist-page-xxx |
显示自定义 404 页面,不泄露信息 |
P1 |
| OPS-008 |
自定义 500 |
触发服务器错误(如有 debug 接口) |
不暴露 stack trace |
P1 |
| OPS-009 |
错误页面一致性 |
各子服务 404 页面 |
风格统一 |
P2 |
| OPS-010 |
API 404 |
GET 不存在的 API 路由 |
返回 JSON {"detail": "Not Found"} |
P1 |
| OPS-011 |
方法不允许 |
POST 到只允许 GET 的页面 |
405 Method Not Allowed |
P1 |
17.3 日志与审计
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| OPS-012 |
登录日志 |
用错误密码登录 3 次,成功 1 次 |
查看审计日志有记录 |
管理员 |
| OPS-013 |
管理操作日志 |
Admin 执行禁用用户操作 |
审计日志有记录,含 actor/time/action |
管理员 |
| OPS-014 |
日志不含敏感 |
检查日志中是否有明文密码/token |
不应明文记录敏感信息 |
P0 |
| OPS-015 |
登出日志 |
登出后检查审计日志 |
有登出记录 |
任意 |
17.4 数据库迁移
| 编号 |
测试内容 |
步骤 |
预期 |
优先级 |
| OPS-016 |
迁移脚本存在 |
检查 alembic/ 或 migrations/ |
有版本化迁移脚本 |
P1 |
| OPS-017 |
迁移幂等性 |
运行同一迁移两次 |
第二次应是无操作(幂等) |
P1 |
| OPS-018 |
回滚脚本存在 |
检查是否有 downgrade 迁移 |
可回滚到上一版本 |
P2 |
三、测试执行流程
四、执行说明
执行策略
| 阶段 |
覆盖模块 |
优先级 |
预计时间 |
| P0 优先 |
模块 1-6 全部 P0 + 模块 7-17 P0 用例 |
~120 用例 |
2-3 小时 |
| P1 全面 |
全部 P1 用例 |
~150 用例 |
2-3 小时 |
| P2 完善 |
全部 P2 用例 |
~96 用例 |
1-2 小时 |
环境要求
工具建议
- 浏览器 DevTools(Console/Network/Performance)
- curl(HTTP 测试、安全头检查)
- Chrome Lighthouse(SEO + Performance)
- axe-core 或 Accessibility Insights(无障碍)
- Burp Suite 或 Postman(安全测试)
五、统计总表
| 模块 |
测试用例数 |
| 模块 1:Home |
24 |
| 模块 2:Auth |
85 |
| 模块 3:Blog |
69 |
| 模块 4:Canvas |
29 |
| 模块 5:Prompt |
36 |
| 模块 6:安全与一致性 |
19 |
| 模块 7:边界与异常输入 |
33 |
| 模块 8:安全性深度测试 |
38 |
| 模块 9:会话管理 |
11 |
| 模块 10:文件上传安全 |
15 |
| 模块 11:搜索边界测试 |
9 |
| 模块 12:SEO 元数据测试 |
22 |
| 模块 13:无障碍深度测试 |
17 |
| 模块 14:性能测试 |
13 |
| 模块 15:移动端交互测试 |
10 |
| 模块 16:跨浏览器兼容性 |
5 |
| 模块 17:运维与部署相关 |
18 |
| 全量合计 |
453 |
文档版本: v4.0 | 最后更新: 2026-05-03