hls.js携带Authorization请求头访问DigitalOcean Spaces报CORS错误
问题原因
这个CORS报错逻辑非常明确:你当前配置的xhrSetup是全局生效规则,会给hls.js发出的所有请求统一加上withCredentials: true和自定义Authorization头——这些请求不止打向你的Laravel后端/stream接口,还包括后续拉取DigitalOcean(DO) Spaces上的二级m3u8文件、ts音频分片的请求。
但DO Spaces默认CORS策略不接受带身份凭证的请求,也不会放行带自定义Authorization头的预检请求,所以请求打到存储桶时直接被浏览器跨域策略拦截。
本地MinIO能正常运行,是因为你自行给MinIO配置了放开权限的CORS规则;删掉xhrSetup配置后DO Spaces能访问,是因为不带自定义头、不带凭证的普通GET请求,本来就在DO默认CORS允许范围内。
最优解决方案(生产可用,符合鉴权要求)
不要让前端给DO Spaces的请求携带鉴权头,改用后端生成临时签名URL的方式实现鉴权,从根源上绕开跨域问题,安全性也更高:
- 先配置DO Spaces的CORS规则(在DO控制台对应存储桶的设置页找到CORS配置项):
- 允许来源:填写前端实际访问地址,本地开发填
http://127.0.0.1:8080,生产环境填线上域名,不要用*通配 - 允许方法:仅开启
GET - 允许头:留空使用默认值即可
- 允许凭证:关闭,不需要开启
- 允许来源:填写前端实际访问地址,本地开发填
- 改造Laravel端的
/songs/{id}/stream接口逻辑:- 接口首先校验请求携带的Bearer令牌合法性,确认用户有对应音频的访问权限
- 权限校验通过后,不要直接返回存储了DO公网固定地址的m3u8内容。先读取原m3u8文件内容,把里面所有DO资源路径(包括二级m3u8、所有ts分片地址)全部替换成DO Spaces生成的临时签名URL
- DO Spaces兼容S3协议,使用官方SDK即可生成自定义有效期的临时签名URL,比如设置1小时有效期,过期后URL自动失效,无权限用户根本拿不到有效地址,完全满足鉴权要求
- 将替换完路径的m3u8内容作为接口响应返回给前端
- 调整前端hls.js配置,取消全局加鉴权头的逻辑,仅在请求自有后端接口时携带令牌,修改后代码如下:
const audio = document.querySelector("#player"); this.player = new Plyr(audio, { controls: ["play", "progress", "current-time", "mute", "volume"], }); if (Hls.isSupported()) { const token = localStorage.getItem("auth-token"); this.hls = new Hls({ debug: true, enableWorker: true, lowLatencyMode: true, backBufferLength: 90, xhrSetup: (xhr, url) => { // 仅请求自有后端接口时携带鉴权头 if (url.startsWith(process.env.VUE_APP_API_ENDPOINT)) { xhr.setRequestHeader("Authorization", "Bearer " + token); // 如果后端不需要cookie跨域传递,这行可以直接删除 // xhr.withCredentials = true; } // 请求DO Spaces资源时走默认逻辑,不携带任何自定义头 }, }); this.hls.loadSource(`${process.env.VUE_APP_API_ENDPOINT}/songs/${this.currentSong.id}/stream`); this.hls.attachMedia(audio); if (this.play) { this.player.play(); } }
这个方案无兼容性问题,鉴权逻辑全部收归后端控制,不会出现资源泄露,也完全符合DO Spaces的安全规则。
临时测试方案(不建议生产环境使用)
如果只是本地调试临时跑通流程,一定要让前端直接带Authorization头请求DO Spaces,可以手动修改DO控制台存储桶的CORS规则:
- 允许来源:必须明确填写前端域名,绝对不能用
*(带凭证的请求不支持通配来源) - 允许方法:开启
GET、OPTIONS - 允许头:添加
Authorization - 允许凭证:开启
Access-Control-Allow-Credentials开关 - 暴露头:添加
Content-Length, Content-Type
但这个方案没有实际鉴权效果——DO Spaces本身不会校验你传递的Bearer令牌,任何人拿到资源公网地址就能直接访问,等于鉴权逻辑完全失效,生产环境不要使用这种配置。
内容的提问来源于stack exchange,提问作者Debarshi Das
相关产品推荐
相关产品推荐

