CDN鉴权与disableRemotePlayback功能不同:前者校验动态token拦截非法请求,后者仅隐藏浏览器投屏按钮;CDN必须校验含videoId、userId、timestamp的HMAC签名,有效期≤300秒,且所有媒体资源(含m3u8、ts、poster、字幕)均需统一鉴权,不可暴露原始URL。

CDN鉴权和disableRemotePlayback是两回事
很多人以为在video标签加disableRemotePlayback就能防投屏,其实它只影响浏览器 UI 层的 AirPlay/Chromecast 图标显示,对 CDN 返回的视频流本身毫无约束力。CDN 鉴权解决的是“谁可以拿到这个视频文件”,而disableRemotePlayback解决的是“用户点不点得着投屏按钮”——前者拦请求,后者只藏菜单。两者必须分开设计、协同使用,不能互相替代。
CDN 必须校验动态 token,不能只靠 Referer
直接配置 CDN 的 Referer 黑白名单(如 Nginx 的 valid_referers)极易被绕过:curl 可伪造、浏览器插件可清除、移动端 WebView 常无 Referer。真正可用的方案是让每个视频请求携带服务端签发的动态 token:
-
video的src指向类似/cdn-proxy/video/123?token=abcde&ts=1729420000&sig=8f3a...这样的代理路径,而非原始 CDN 地址 - CDN 边缘节点或自建反向代理(如 Nginx + Lua / OpenResty)在转发前解析并校验
ts(时间戳)、sig(HMAC-SHA256 签名)、token(绑定用户 ID 或 session) - 签名原文应包含至少三项:
videoId:userId:timestamp:secret,且timestamp有效期建议 ≤ 300 秒 - 校验失败统一返回
403,不暴露任何资源存在性信息(避免泄露 videoId 是否合法)
CDN 配置需同步放开必要头与跨域策略
若用 fetch + URL.createObjectURL() 加载 blob(常见于高安全场景),CDN 必须支持以下响应头,否则播放器无法分片加载或拖动进度条:
-
Access-Control-Allow-Origin: https://your-site.com(禁止用*,否则 Blob 播放会失败) -
Access-Control-Allow-Credentials: true(若依赖 Cookie 鉴权) -
Accept-Ranges: bytes和Content-Range(HLS/DASH 分片或 MP4 流式拖动必需) -
X-Content-Type-Options: nosniff(防止 MIME 类型嗅探导致误执行)
同时,在 CSP 中明确声明 media-src 'self' https://cdn.yourdomain.com;,避免因策略过严导致分片加载被拦截。
立即学习“前端免费学习笔记(深入)”;
投屏防护的边界必须认清
哪怕 CDN 鉴权滴水不漏,也无法阻止以下行为:
- 用户开启 macOS QuickTime 屏幕录制,或 Windows Xbox Game Bar 录制整个窗口
- 用另一台手机拍摄投屏画面(物理盗录,所有前端/CDN 层手段失效)
- 抓包获取已通过鉴权的 HLS
.m3u8地址后,用 ffmpeg 直接下载(需服务端对每个.ts分片也做 token 校验)
真正的防线在服务端闭环:每个媒体请求(包括 poster 图、字幕 <track src></track>、HLS 的 playlist 和 segment)都必须走同一套 token 校验逻辑,且不能把原始 S3 URL 或公开 CDN 地址暴露给前端 DOM。



















