1. 接口规范
1.1 RESTful 请求方式
| 请求方式 | 用途 | 示例 |
| GET | 查询数据 | GET /api/article/index?page=1&limit=10 |
| POST | 新增数据 | POST /api/article/save |
| PUT | 修改数据 | PUT /api/article/update/1 |
| DELETE | 删除数据 | DELETE /api/article/delete/1 |
1.2 统一返回格式
// 成功响应
{
"code": 200,
"msg": "操作成功",
"data": {...}
}
// 失败响应
{
"code": 500,
"msg": "操作失败原因",
"data": []
}
1.3 分页返回说明
// 分页查询返回结构
{
"code": 200,
"msg": "操作成功",
"data": {
"list": [ ... ], // 数据列表
"total": 100, // 总记录数
"per_page": 10, // 每页数量
"current_page": 1, // 当前页码
"last_page": 10 // 最后一页
}
}
1.4 错误码说明
| code | 含义 | 说明 |
| 200 | 成功 | 请求处理成功 |
| 400 | 参数错误 | 请求参数不合法或缺失 |
| 401 | 未认证 | Token 缺失、过期或无效 |
| 403 | 无权限 | 当前用户角色无权访问该接口 |
| 404 | 资源不存在 | 请求的数据记录不存在 |
| 422 | 验证失败 | 数据验证不通过,msg 中包含详细原因 |
| 500 | 服务器错误 | 服务端内部异常 |
2. 架构概述
请求处理流程
客户端请求
↓
[路由分发] route/api.php
↓
├── 公开路由组(无需Token)
│ └── AuthController、IndexController 等
│
└── 鉴权路由组(需要Token + RBAC权限)
├── CorsMiddleware → 处理跨域
├── AuthCheck → 验证JWT Token
├── PermissionCheck → 校验角色权限
└── 业务Controller → 处理请求
公开路由 vs 鉴权路由
| 特征 | 公开路由 | 鉴权路由 |
| 是否需要Token | ❌ 不需要 | ✅ 必须携带 |
| 中间件 | 无或仅CORS | CORS + AuthCheck + PermissionCheck |
| 典型接口 | 登录、注册、公开内容 | 数据的增删改查 |
| 路由前缀 | /api/public/... 或 /api/... | /api/{module}/... |
| 访问频率 | 较高 | 按用户角色限制 |
3. JWT 认证
3.1 登录获取 Token
// 请求
POST /api/public/auth/login
Content-Type: application/json
{
"username": "admin",
"password": "123456"
}
// 成功响应
{
"code": 200,
"msg": "登录成功",
"data": {
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"expire_time": 7200,
"user_info": {
"id": 1,
"username": "admin",
"role": "super_admin"
}
}
}
3.2 刷新 Token
// 请求
POST /api/public/auth/refresh
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
// 成功响应
{
"code": 200,
"msg": "Token刷新成功",
"data": {
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
"expire_time": 7200
}
}
3.3 携带 Token 访问接口
// 请求头携带 Token
GET /api/article/index?page=1&limit=10
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
3.4 JWT 认证流程详解
| 步骤 | 说明 |
| 1. 用户登录 | 提交用户名+密码,服务端验证后生成 JWT Token,包含用户ID和角色信息 |
| 2. 客户端存储 | 客户端将 Token 存储在 localStorage 或 sessionStorage 中 |
| 3. 携带请求 | 每次请求在 Header 中携带 Authorization: Bearer {token} |
| 4. 中间件验证 | AuthCheck 中间件解析 Token,验证签名和有效期,注入用户信息 |
| 5. 权限校验 | PermissionCheck 中间件校验用户角色是否有权访问当前路由节点 |
| 6. 业务处理 | 控制器通过 $this->loginUser 获取当前用户信息,执行业务逻辑 |
3.5 JWT 安全机制
| 机制 | 说明 |
| 签名算法 | HS256 (HMAC-SHA256),服务端密钥签名,防篡改 |
| Token 有效期 | 默认 2 小时(7200秒),可通过 refresh 接口续期 |
| Payload | 包含 user_id、role、iat(签发时间)、exp(过期时间) |
| 无状态 | 服务端不存储 Token,减轻服务器压力,天然支持分布式 |
| HTTPS 传输 | 生产环境必须使用 HTTPS 传输,防止 Token 被中间人截获 |
3.6 控制器中获取当前用户
// 通过 AuthCheck 中间件注入的 $loginUser 属性
$userId = $this->loginUser['id']; // 用户ID
$userName = $this->loginUser['username']; // 用户名
$userRole = $this->loginUser['role']; // 角色标识
// 或使用 BaseController 提供的便捷方法
$userId = $this->getLoginUserId();
$userInfo = $this->getLoginUser();
$isSuperAdmin = $this->isSuperAdmin();
4. 完整路由表
4.1 公开路由(8 条,无需 Token)
| 方法 | 路由 | 说明 |
| POST | /api/public/auth/login | 用户登录,返回JWT Token |
| POST | /api/public/auth/refresh | 刷新Token(需携带旧Token) |
| GET | /api/public/index/config | 获取站点配置信息 |
| GET | /api/public/index/categories | 获取全部分类树 |
| GET | /api/public/index/articles | 公开文章列表(分页) |
| GET | /api/public/index/article/:id | 公开文章详情 |
| GET | /api/public/index/links | 友情链接列表 |
| GET | /api/public/index/search | 全站搜索 |
4.2 文章管理模块路由(需 Token)
| 方法 | 路由 | 说明 |
| GET | /api/article/index | 文章分页列表 |
| POST | /api/article/save | 新增文章 |
| GET | /api/article/read/:id | 文章详情 |
| PUT | /api/article/update/:id | 更新文章 |
| DELETE | /api/article/delete/:id | 删除文章 |
| DELETE | /api/article/delete_batch | 批量删除 |
4.3 其他鉴权模块路由(汇总)
| 模块 | 路由前缀 | 接口数 | 说明 |
| 分类管理 | /api/category/ | 7 | 分类CRUD、排序、树形结构 |
| 管理员 | /api/admin/ | 6 | 管理员CRUD、角色分配、密码重置 |
| 角色权限 | /api/role/ | 5 | 角色CRUD、权限节点分配 |
| 用户管理 | /api/user/ | 6 | 前台用户CRUD、状态管理 |
| 评论管理 | /api/comment/ | 5 | 评论审核、批量操作 |
| 媒体资源 | /api/upload/ | 4 | 文件上传、列表、删除 |
| 系统配置 | /api/config/ | 3 | 配置读取、保存、分组列表 |
| 菜单管理 | /api/menu/ | 5 | 后台菜单CRUD、排序 |
| 主题管理 | /api/theme/ | 4 | 主题列表、切换、配置 |
| 插件管理 | /api/plugin/ | 5 | 插件安装、启用、配置 |
| 日志管理 | /api/log/ | 3 | 操作日志查询、清理 |
以上鉴权路由共 55+ 条接口,覆盖 XPCMS 全部后台管理功能。
5. 控制器开发模板
以下以 Article 模块为例,展示完整的 xpapi 应用控制器开发方式:
<?php
declare(strict_types=1);
/**
* 模块描述:API文章管理控制器
* 作者:彭浩
* 邮箱:2443257717@qq.com
* 开发时间:2026-08-02
* 版权:由彭浩独家所有,未经授权禁止转载或商业使用
*/
namespace app\xpapi\controller;
use app\common\service\ArticleService;
use app\xpapi\validate\Article as ArticleValidate;
use think\Response;
class Article extends BaseController
{
/**
* 获取文章分页列表
* @param int $page 页码
* @param int $limit 每页数量
* @param string $keyword 搜索关键词
* @return Response
*/
public function index(): Response
{
$page = $this->request->param('page', 1);
$limit = $this->request->param('limit', 10);
$keyword = $this->request->param('keyword', '');
$articleService = $this->app->make(ArticleService::class);
$result = $articleService->getList($page, $limit, $keyword);
return $this->success('获取成功', $result);
}
/**
* 新增文章
* @return Response
* @throws \Exception
*/
public function save(): Response
{
$validate = new ArticleValidate();
if (!$validate->scene('save')->check($this->request->post())) {
return $this->error($validate->getError(), 422);
}
$articleService = $this->app->make(ArticleService::class);
$data = $this->request->post();
$data['author_id'] = $this->getLoginUserId();
$id = $articleService->createArticle($data);
return $this->success('新增成功', ['id' => $id]);
}
/**
* 更新文章
* @param int $id 文章ID
* @return Response
*/
public function update(int $id): Response
{
$validate = new ArticleValidate();
$data = array_merge(['id' => $id], $this->request->put());
if (!$validate->scene('update')->check($data)) {
return $this->error($validate->getError(), 422);
}
$articleService = $this->app->make(ArticleService::class);
$articleService->updateArticle($id, $this->request->put());
return $this->success('更新成功');
}
/**
* 删除文章
* @param int $id 文章ID
* @return Response
*/
public function delete(int $id): Response
{
$articleService = $this->app->make(ArticleService::class);
$articleService->deleteArticle($id);
return $this->success('删除成功');
}
}
6. 安全规范
6.1 SQL 注入防护
| 措施 | 说明 |
| 参数绑定 | ThinkPHP 查询构造器自动使用 PDO 参数绑定,避免拼接 SQL |
| 禁止原生 SQL | 禁止在控制器中使用 Db::query() 拼接用户输入 |
| 输入过滤 | 所有用户输入通过验证器过滤后再传入模型层 |
| 字段白名单 | 使用 allowField() 限制可写入字段,防止批量赋值漏洞 |
6.2 XSS 跨站脚本防护
| 措施 | 说明 |
| 默认转义 | ThinkPHP 模板输出默认对变量进行 HTML 转义 |
| 富文本过滤 | 用户提交的 HTML 内容使用 HTMLPurifier 过滤危险标签 |
| 输入验证 | 所有输入字段进行类型和格式校验 |
| Content-Type | API 响应设置正确的 Content-Type: application/json |
6.3 密码安全
| 措施 | 说明 |
| 加密算法 | 使用 password_hash() (bcrypt) 单向哈希存储 |
| 密码强度 | 强制要求密码长度 ≥ 8 位,包含字母+数字 |
| 登录限制 | 连续 5 次失败锁定账号 15 分钟 |
| 明文禁止 | 密码在任何日志、响应中不得以明文出现 |
6.4 CSRF 防护
| 措施 | 说明 |
| RESTful API | 纯 API 应用天然不易受 CSRF 攻击(无 Cookie 认证) |
| JWT Header | Token 通过 Authorization 头传递,浏览器不会自动携带 |
| CORS 白名单 | CorsMiddleware 仅允许已配置的域名跨域访问 |
| 同源策略 | 生产环境配置合理的 Access-Control-Allow-Origin |
6.5 接口安全最佳实践清单
| 序号 | 实践 | 说明 |
| 1 | HTTPS 强制 | 生产环境必须使用 HTTPS,禁止明文 HTTP 传输 |
| 2 | Token 过期 | 设置合理的 Token 有效期,定期刷新 |
| 3 | 频率限制 | 对登录、注册等敏感接口实施速率限制 |
| 4 | 错误信息 | 生产环境不暴露详细错误堆栈,仅返回通用错误码 |
| 5 | 日志记录 | 关键操作(增删改)记录操作日志,包含用户ID和时间 |
| 6 | 敏感数据 | 响应中不返回密码、密钥等敏感字段 |
| 7 | 请求大小 | 限制上传文件大小和请求体大小 |
| 8 | 参数校验 | 所有接口参数必须通过验证器校验,信任零输入原则 |