VVCMS 接口调用注意事项、认证失败锁定与操作审计

最后更新时间:2026-09-22 18:43:41

1. 调用注意事项

  1. 不要把真实 Token 写入代码仓库、文档或聊天记录。
  2. 栏目删除前必须先删除或迁移栏目下的内容。
  3. MCP 工具只需要传必填字段和要修改的字段:内容工具的必填项是 titlecolumn_idid,栏目工具是 nameslugid
  4. create_columncreate_article 以及外部 API 的创建接口成功后会返回新建记录的 id,可以直接用它继续调用 get_* / update_* / delete_*。批量导入时按这个 id 建立本地映射即可,不必再查一次列表。
  5. list_articles 的筛选字段全部可选,只传 currentsize 即可分页;size 超过 100 时按 100 处理。
  6. update_article 未提供的字段保持原值,不会因部分更新清空正文。
  7. 文章访问密码不会通过 MCP 返回。
  8. API 文件上传使用 multipart/form-data;MCP 文件上传使用 Base64 JSON。
  9. 相同文件可能因 SHA-256 去重直接返回已有文件路径。
  10. 图片是否转换为 WebP 由全局上传配置决定。
  11. 主题文件工具只允许访问当前主题目录,并拒绝目录穿越和越界符号链接;delete_theme_file 只删普通文件,delete_theme_directory 只删空目录,两者都不做递归删除。
  12. 生产环境建议通过 HTTPS、网关白名单或网络隔离保护外部 Token 接口。
  13. 认证失败会被临时锁定,见下一节。

2. 认证失败锁定

为避免外部 Token 接口被暴力尝试,后台「安全配置」提供按来源 IP 的失败锁定,同时作用于外部 API、MCP 与后台管理接口。

配置接口(后台 VToken,仅管理员):

GET /api/admin/option/security/get
POST /api/admin/option/security/update
Content-Type: application/json
VToken: YOUR_VTOKEN
{
  "auth_guard_enabled": true,
  "auth_guard_max_failures": 10,
  "auth_guard_block_seconds": 600,
  "auth_guard_trust_proxy": false
}

2.1 行为说明

  • 只有携带了凭证但校验失败的请求才计数(无效 Bearer Token、无效 VToken、凭证有效但越权访问管理接口)。未携带凭证的请求不计数,避免未登录状态的正常访问被误锁。
  • 连续失败达到 auth_guard_max_failures 后,该来源 IP 被锁定 auth_guard_block_seconds 秒;锁定期间所有需要认证的接口返回 HTTP 429,并带 Retry-After 头。
  • 一次认证成功且请求最终未被拒绝才清零该 IP 的连续失败次数。判定不只看中间件是否中断请求,还看最终响应状态码:MCP 端点的权限判断在业务处理内部完成(直接返回 403,不会中断中间件链),这类请求同样计入失败,否则刚记录的失败会被立刻清零、越权请求永远攒不满阈值。
  • /api/public/ 前缀的接口(登录、验证码等)不参与计数,也不会被锁定拦截,避免锁定后无法自愈。注意:这条规则也意味着 /api/public/login 的密码尝试不受本机制限制(目前只依赖验证码等业务手段),如需覆盖需按接口粒度单独接入计数。
  • auth_guard_trust_proxy 决定是否采信 X-Forwarded-For / X-Real-IP:部署在 Nginx 等反向代理后必须开启,否则所有请求都会被识别为代理机来源;直连部署应保持关闭,避免伪造该头部绕过锁定。
  • 计数保存在进程内存中,重启服务即清空

3. 操作审计日志

栏目、内容、文件的关键写操作(新增 / 编辑 / 删除)都会写入事件日志表,可在后台「系统管理 → 系统日志 → 事件日志」中查看。

记录的 model 字段区分来源:

model说明
admin管理端后台操作(/api/admin/*
api外部开放接口(/api/api_*,Bearer Token 鉴权)
mcpMCP 工具调用

其余字段:type(add / edit / delete / query / option / login)、op(操作名,如 content_updateupload_file)、objIdobjNameuidunameipstate(1 成功、2 失败),以及 changeName / changeBefore / changeAfer

3.1 覆盖范围

  • 栏目:创建、更新、更新单页、删除
  • 内容:创建(含外部投稿)、更新、删除、批量删除
  • 文件:外部接口上传、MCP upload_file
  • MCP:栏目与内容的增删改、主题文件新建/编辑、主题目录新建

3.2 说明

  1. 审计与管理端共用同一批 service handler,因此管理端操作也会留痕,model 记为 admin;外部接口记为 api
  2. 失败的操作同样记录state 为 2。反复失败的删除或上传尝试往往比成功更有排查价值。
  3. MCP 不经过 gin 中间件,由 handler 直接写库;写库失败只记 slog,不会影响工具返回结果。
  4. 对象名称、操作名、变更前后会按数据库列宽截断(20~255 字符),保证不会因为超长标题导致整条审计记录写入失败。
  5. MCP 的 update_article 在标题发生变化时记录 changeBefore / changeAfer,标题未变化时不写变更字段。

4. 日志保留与清理

事件日志(MCP / API / 管理端操作审计)与发送日志按保留天数自动清理,避免日志表无限增长。

配置项(option key log):

{
  "keep_days": 90,
  "auto_cleanup_enabled": true
}
字段说明
keep_days保留天数,只保留最近 N 天。0 表示不清理、永久保留;取值上限 3650 天(10 年)。默认 90。
auto_cleanup_enabled是否开启每日自动清理,默认 true

4.1 接口

  • GET /api/admin/option/log/get 获取配置
  • POST /api/admin/option/log/update 保存配置
  • POST /api/admin/log/cleanup 立即清理一次,返回 {keep_days, event_deleted, send_deleted, before, skipped}

4.2 行为说明

  1. 自动清理在进程启动时拉起,首次延后 1 分钟执行(避开启动期的数据库迁移),之后每 12 小时一次;单次清理最多执行 5 分钟。
  2. 删除按 500 条一批进行:先取一批过期 ID 再按主键删除。日志表可能积累几十万行,一次性 DELETE 会产生超大事务、长时间锁表;分批既能控制单批规模,也避开 SQLite 默认编译选项不支持 DELETE ... LIMIT 的问题。
  3. keep_days0 或关闭自动清理时,清理任务会跳过,不删除任何数据;改配置无需重启。
  4. 两台以上实例同时部署时清理会并发执行,但删除条件是幂等的时间边界,不会误删。