thinkphp 6 应使用 hash::make($roomid . uniqid() . random_int(1000,9999)) 生成唯一有时效的 stream_key,并存入 rooms 表,配 stream_key_expired_at 字段校验过期、is_used 字段防重放,且仅服务端比对、不返回前端。

ThinkPHP 6 如何生成安全的 stream_key 并绑定房间
stream_key 不是随便拼的字符串,它必须满足两个条件:唯一性(防重放)、有时效性(防盗用)。直接写死或用用户 ID 当 key,上线后很快会被刷流或恶意推流。
推荐做法是用 ThinkPHP 的 Hash::make() + 时间戳 + 房间 ID 混合生成,并存入 rooms 表的 stream_key 字段:
- 生成时调用
md5($roomId . time() . $salt)或更稳妥的Hash::make($roomId . uniqid() . random_int(1000,9999)) - 务必设置过期时间字段
stream_key_expired_at(如 2 小时后失效),后续鉴权时用time() > $room->stream_key_expired_at校验 - 推流前必须通过接口校验该 key 是否有效、是否已被使用(比如加
is_used布尔字段) - 不要把
stream_key直接返回给前端页面,只在服务端用于比对 SRS 的on_publish回调参数
如何让 SRS 的 on_publish 回调真正验证 PHP 后端权限
SRS 的 on_publish 是 HTTP 请求,它会带上 app、name、client_id 等参数,但不会自动带 token 或 session。你不能靠 Cookie 或 Session 来判断——因为这是流媒体服务器发来的请求,不是浏览器发的。
正确做法是:在 SRS 配置里把回调 URL 拼上签名参数,PHP 接口收到后做三件事:
- 检查
sign参数是否由服务端密钥 +name+timestamp生成(例如hash_hmac('sha256', $name . $ts, $secret)) - 拒绝
timestamp超过 5 分钟的请求(防重放) - 查数据库确认
name对应的stream_key存在、未过期、且is_live = 0(防止重复推流) - 成功则返回
{"code":0,"msg":"success"};失败必须返回非 0 状态码(如 403),否则 SRS 仍会接受推流
为什么直播房间状态更新总不同步?
常见现象是:主播已开播,但房间列表页还显示“未开播”;或者主播断流了,后台没及时标记 is_live = 0。根本原因在于依赖“心跳轮询”或“前端上报”,不可靠。
SRS / ZLMediaKit 提供的 on_close 或 on_unpublish 回调才是唯一可信来源:
- 必须监听这两个回调,并在 PHP 接口中更新
rooms.is_live和rooms.last_offline_at - 不要在前端 JS 里调
POST /api/room/end—— 用户关页面、断网、杀进程都会导致该请求丢失 - 为防回调丢失,可加兜底逻辑:定时任务扫描
last_online_at 且 <code>is_live = 1的房间,自动设为下线 - Redis 缓存房间状态时,key 命名建议用
room:status:{room_id},TTL 设为 90 秒,与回调强一致
ThinkPHP 接口返回播放地址时,HLS 和 FLV 怎么选?
别硬编码返回 .m3u8 或 .flv,要按终端能力动态决策。浏览器兼容性差异极大:
- PC Chrome / Edge:优先返回 HTTP-FLV(低延迟),用
flv.js播放;fallback 到 HLS - iOS Safari / 微信内置浏览器:只能用 HLS(
http://{domain}/live/{stream_name}.m3u8),FLV 会静音或黑屏 - 移动端 WebView(Android):视内核而定,建议统一走 HLS 更稳
- 返回结构示例:
{"play_type":"hls","url":"https://cdn.example.com/live/abc123.m3u8","flv_url":"http://stream.example.com/live/abc123.flv"}
复杂点在于 CDN 域名和流媒体服务器域名通常不一致,url 必须从配置读取,不能拼接硬写;stream_name 必须和数据库里存的 stream_key 严格一致,大小写敏感。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











