ThinkPHP8需自行实现授权异步校验:后端提供受Token保护的/api/auth/check接口,基于策略动态校验权限;前端按需发起fetch请求并响应,但所有敏感操作仍须服务端二次鉴权。

ThinkPHP8 本身不内置“授权异步校验”功能,它需要你结合权限控制中间件、前端事件与后端 API 接口协同实现。所谓“异步校验”,本质是:用户操作(如点击按钮、提交表单)前,不阻塞页面,由 JavaScript 发起一次轻量请求,向后端确认当前用户是否具备某项权限,再决定是否允许操作或展示提示。
一、后端准备权限校验接口
不能依赖控制器里写 if 判断,而要提供一个标准、无副作用的 API 接口:
- 新建控制器 app/controller/Api/Auth.php,定义 check 方法
- 接收两个必要参数:
permission(如video.delete)和可选的resource_id(用于细粒度控制) - 使用框架自带的权限服务校验:
Auth::check($permission, $resource_id ?? null) - 返回统一 JSON 格式:
{"allowed": true, "reason": "ok"}或{"allowed": false, "reason": "no_permission"} - 该接口必须通过 Token 中间件保护(参考 ThinkPHP8 Token 验证最佳实践),确保调用者已登录且身份可信
二、前端发起异步请求并响应
不要在点击瞬间才去请求——应提前加载、缓存或按需触发:
- 对关键按钮(如“删除短剧”)添加 data-permission 属性:
<button data-permission="video.delete">删除</button> - 绑定 click 事件,先禁用按钮防止重复点击,再发起 fetch:
- 请求成功后,若
allowed === false,弹出提示(如“权限不足”)并恢复按钮;若为 true,则继续执行真实业务逻辑(如跳转、弹窗、调用删除接口) - 建议加防抖或节流,避免高频点击反复请求(尤其在列表批量操作场景)
三、权限判断必须基于策略,而非硬编码
异步校验的价值在于支持动态、上下文相关的权限,因此后端逻辑不能是简单查角色表:
立即学习“PHP免费学习笔记(深入)”;
- 推荐使用 RBAC + 策略扩展(如自定义
Auth::define()规则),例如:Auth::define('video.edit', function ($user, $videoId) { return Db::name('videos')->where(['id' => $videoId, 'user_id' => $user['id']])->find(); }); - 这样前端传
video.edit和resource_id=1024,后端就能判断“当前用户是否拥有编辑该视频的权限”,而不是笼统地看有没有“编辑视频”角色 - 避免在接口里写
if ($user['role'] === 'admin') {...}这类硬编码逻辑,否则无法支持多角色、条件授权等演进需求
四、安全边界必须守住
异步校验只是用户体验优化,绝不能替代服务端真实鉴权:
- 前端返回
allowed: true,只代表“此刻有权限”,不代表可以绕过后续接口的权限检查 - 所有敏感操作的最终接口(如
/api/v1/video/1024/delete)仍需在对应控制器方法中再次调用Auth::check()或使用@auth注解拦截 - 禁止将权限判断逻辑暴露在前端 JS 中(如把 permission list 全量下发),防止被篡改或遍历
- 接口响应建议设置
Cache-Control: no-store,禁止浏览器或 CDN 缓存结果



















