首页 / 开发文档 / API 接口

API 接口文档

XPCMS 通过 xpapi 应用提供标准 RESTful 接口,采用 JWT (JSON Web Token) 无状态认证机制,支持第三方客户端接入、小程序对接和前后端分离开发。

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❌ 不需要✅ 必须携带
中间件无或仅CORSCORS + 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-TypeAPI 响应设置正确的 Content-Type: application/json

6.3 密码安全

措施说明
加密算法使用 password_hash() (bcrypt) 单向哈希存储
密码强度强制要求密码长度 ≥ 8 位,包含字母+数字
登录限制连续 5 次失败锁定账号 15 分钟
明文禁止密码在任何日志、响应中不得以明文出现

6.4 CSRF 防护

措施说明
RESTful API纯 API 应用天然不易受 CSRF 攻击(无 Cookie 认证)
JWT HeaderToken 通过 Authorization 头传递,浏览器不会自动携带
CORS 白名单CorsMiddleware 仅允许已配置的域名跨域访问
同源策略生产环境配置合理的 Access-Control-Allow-Origin

6.5 接口安全最佳实践清单

序号实践说明
1HTTPS 强制生产环境必须使用 HTTPS,禁止明文 HTTP 传输
2Token 过期设置合理的 Token 有效期,定期刷新
3频率限制对登录、注册等敏感接口实施速率限制
4错误信息生产环境不暴露详细错误堆栈,仅返回通用错误码
5日志记录关键操作(增删改)记录操作日志,包含用户ID和时间
6敏感数据响应中不返回密码、密钥等敏感字段
7请求大小限制上传文件大小和请求体大小
8参数校验所有接口参数必须通过验证器校验,信任零输入原则