关键在于避免视频URL出现在src属性中,应采用MediaSource分片加载或服务端动态代理生成带时效、身份绑定及签名的临时地址,杜绝直链泄露。

HTML 视频无法真正“防投屏”,但直链泄露是可防的——关键在于不让浏览器拿到完整、可复用的视频 URL。投屏本身是系统级行为,前端无权拦截;而直链一旦出现在 src 或 source 属性里,就等于把钥匙交到用户手里。
为什么 video.src = "xxx.mp4" 会导致直链泄露
只要视频地址写死在 HTML 或 JS 变量里,用户就能通过以下任意方式拿到:
- DevTools → Elements 面板直接查看
- Network 面板过滤
media或mp4,点开请求看 Headers →Request URL - 禁用 JS 后,若 fallback 逻辑暴露了原始地址,照样能下载
这不是“用户技术高”,而是浏览器设计使然:所有资源加载路径必须对开发者可见。所以任何试图“藏 URL”的做法(比如 base64 编码、字符串拼接、CSS 遮罩)都无效。
用 MediaSource + 分片请求切断直链路径
这是目前唯一能避免完整 URL 出现在 DevTools 中的方案。核心是不使用 src 属性,改用 URL.createObjectURL(mediaSource),再通过 fetch 拉取加密分片,喂给 SourceBuffer。
实操要点:
-
video标签必须初始化时留空src,且不写标签 - 服务端需支持
Range请求,并对每个分片校验token和user_id(不能只校验一次) - 分片 URL 示例:
/api/video/chunk?id=vid_abc&seq=001&token=xyz789,token应含时间戳和签名,有效期建议 ≤ 60 秒 - 前端 fetch 时务必带
credentials: 'include'或Authorization头,否则服务端拿不到会话上下文
服务端代理 URL 必须带强绑定参数
如果不用 MSE,至少得走代理层。但 /proxy/video/xxx 这种静态路径仍危险——它可能被缓存、被猜出、被反复调用。真正安全的是动态生成的带参地址:
- 必须含时效性参数:
t=1729418760(Unix 时间戳),服务端校验是否超时(建议 ≤ 300 秒) - 必须含身份绑定:
u=user_123,且与当前登录态一致(不能仅靠前端传,要和服务端 session 对齐) - 必须含签名:
s=abcd1234,由hmac(secret, `${id}:${u}:${t}`)生成,服务端重新计算比对 - Nginx 或 API 网关需拦截该路径,校验通过后才反向代理到 S3/CDN,禁止直接返回 302 跳转
Referer 和 User-Agent 校验只是辅助,别当真
它们能挡住批量爬虫或小白用户,但对真实盗链几乎无效:
-
Referer可被 curl / Postman 伪造:curl -H "Referer: https://your-site.com" ... -
User-Agent字段在 Chrome 投屏时会变成Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36... Chrome/128.0.0.0 Safari/537.36,和普通桌面访问一样 - 空 Referer 在投屏、PWA 启动、微信内嵌页等场景天然存在,若配置为拒绝,会导致合法用户无法播放
真正复杂的是签名时效性和服务端状态同步——比如用户中途登出,已签发的 token 是否立即失效?这需要 Redis 记录活跃播放会话,或采用 JWT 并设置短生命周期,而不是依赖单次 HMAC 签名。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











