ThinkPHP6权限控制核心是请求入口拦截:未登录、未付费、非会员用户禁止访问课程/音频/PDF;通过中间件校验登录态、订单有效性及VIP时效,不满足则返回403或跳转支付页。

用 ThinkPHP6.x 搭建知识付费系统的权限控制,关键不在框架多复杂,而在于“谁能看到什么内容”这件事必须在请求入口就拦住——课程、音频、PDF 文档这些资源,不能靠前端藏链接来保护。
用户身份与内容权限绑定
系统需明确区分三类基础状态:未登录用户、已登录但未付费的普通用户、已购买或开通会员的授权用户。ThinkPHP6 的中间件(Middleware)是拦截请求的第一道关卡,比如访问某个音频播放页 /course/audio/123,中间件应立即查:
• 当前用户是否登录
• 该课程 ID 是否在用户已购订单表中存在有效记录
• 或者用户是否处于 VIP 有效期(查会员表 + 时间判断)
不满足任一条件,直接返回 403 或跳转支付页,不渲染任何内容。
音频与图文内容的动态访问控制
音频文件(MP3)、图文页面(HTML/Markdown 渲染结果)不能直接暴露真实路径。正确做法是:
• 音频资源不放在 public 目录下,而是存于 runtime 或私有存储(如阿里云 OSS 私有 Bucket)
• 前端播放器 src 指向一个受控路由,例如 /api/play/audio?cid=123&token=xxx
• 后端控制器中验证 token 有效性(可基于用户 ID + 课程 ID + 时间戳生成签名),再通过 file_get_contents + header 流式输出,或生成临时直链(OSS STS 临时凭证)
• 图文内容同理,阅读接口需校验权限,渲染前检查课程状态(是否上架、是否过期、是否限免)
防止试听/预览内容被滥用
很多课程提供前 3 分钟试听,这部分内容仍需防搬运:
• 试听音频单独切片存储,文件名不带课程 ID,避免枚举
• 播放页 JS 中禁用右键、禁用开发者工具下载(基础防护,配合后端才有效)
• 更进一步可在音频流中嵌入动态水印(如用户手机号末四位),需服务端转码支持
• 图文试读限制段落数量或字数,后端渲染时截断并加“开通会员继续阅读”提示
立即学习“PHP免费学习笔记(深入)”;
数据库权限字段设计要点
权限逻辑最终落在数据结构上,几个关键字段建议:
• order 表:status(1=已支付)、expire_time(单课有效期,NULL 表示永久)、refunded(是否已退款)
• user_vip 表:level(1=月度/2=年度/3=终身)、start_time、end_time
• course 表:is_free(是否免费)、price(定价)、pay_type(0=单买/1=会员可见/2=两者都可)
查权限时组合查询,例如:用户买了课 OR 是有效期内的对应等级 VIP → 才允许播放



















