如何通过AWS签名Cookie保护AWS流媒体HLS的.ts及子播放列表文件
HLS .ts分片缺失AWS安全校验无法播放的可行解决方案
方案1:服务端改写M3U8文件内容拼接签名参数
这是兼容性最好的方案,不需要修改前端播放器逻辑:
- 生成签名时将Policy的资源路径设置为
/hls/*这类通配格式,保证同一个签名对当前目录下所有.ts分片都生效 - 可以在源站、CloudFront Functions/Lambda@Edge层处理M3U8文件的返回逻辑:提取用户请求M3U8时携带的
Policy、Signature、Key-Pair-Id三个参数,遍历M3U8内所有.ts后缀的分片路径,把三个签名参数统一拼接到每个分片URL的查询字符串中 - 播放器解析M3U8时拿到的直接是带完整签名的.ts地址,请求时自动携带校验参数
方案2:前端通过Video.js请求钩子统一追加参数
如果暂时无法修改服务端逻辑,可以直接在播放器层做拦截:
- 先从主M3U8的URL中提取出三个安全签名参数,存储在前端全局变量中
- 注册Video.js的
beforeRequest钩子,拦截所有播放器发出的资源请求,匹配到.ts后缀的请求时自动把签名参数拼接到URL末尾
示例代码:
// 先从当前页面加载的M3U8地址中提取签名参数,示例逻辑可自行调整 const m3u8Url = 'https://{cloudfront_url}/hls/sample_1920x1080.m3u8?Policy={policy}&Signature={signature}&Key-Pair-Id={keypair_id}' const urlObj = new URL(m3u8Url) const hlsSignParams = { Policy: urlObj.searchParams.get('Policy'), Signature: urlObj.searchParams.get('Signature'), 'Key-Pair-Id': urlObj.searchParams.get('Key-Pair-Id') } // 初始化播放器后注册拦截钩子 const player = videojs('my-player') player.on('beforeRequest', (event, request) => { if (request.uri.endsWith('.ts')) { const hasQuery = request.uri.includes('?') request.uri += `${hasQuery ? '&' : '?'}Policy=${hlsSignParams.Policy}&Signature=${hlsSignParams.Signature}&Key-Pair-Id=${hlsSignParams['Key-Pair-Id']}` } })
方案3:改用CloudFront签名Cookie替代URL签名
如果你的流媒体资源和前端站点在同一个一级域名下,用签名Cookie是最省事的方案:
- 用户请求主M3U8文件时,服务端返回响应时给浏览器种下CloudFront要求的三个签名Cookie,Cookie的Path设置为
/hls/,Domain配置为对应根域名 - 所有浏览器发起的资源请求(包括播放器自动发起的.ts分片请求)都会自动携带符合校验要求的Cookie,不需要修改任何URL或者播放器逻辑
- 跨域场景需要额外配置CloudFront的CORS规则允许凭证传输,否则Cookie无法正常携带
注意事项
- 所有方案都要求你生成的签名策略必须覆盖.ts分片的资源路径,不能只授权单独的M3U8文件路径,否则即使拼上参数也会校验失败
- 如果用URL签名,注意参数转义,避免特殊字符导致请求异常
内容的提问来源于stack exchange,提问作者user16838528
相关产品推荐
相关产品推荐

