hls.js CORS使用AWS Cloudfront问题使用Cookie

时间:2017-07-07 00:56:11

标签: cookies xmlhttprequest cors amazon-cloudfront hls.js

我尝试使用Cloudfront HLS功能设置视频流,但我无法让Hls.js在请求中发送我的凭据Cookie。

我已将Cloudfront配置为转发Cookie并转发访问控制标头。我还设置了我的S3 CORS策略以包含GET,HEAD。

我遇到的问题是即使我设置了xhr.withCredentials = true并且会话中定义了cookie,当我使用chrome控制台查看请求时,我可以看到HLS请求没有cookie。因此,我从cloudfront收到错误响应,说我需要包含凭据cookie。

代码: 首先,我向服务器发出ajax请求以生成cookie。服务器返回在浏览器中存储为会话cookie的三个Set-Cookies标头:

$.ajax(
{
type: 'GET',
url: 'http://subdomain.mydomain.com:8080/service-
webapp/rest/resourceurl/cookies/98400738-a415-4e32-898c-9592d48d1ad7',
success: function (data) {
        playMyVideo();
},
headers: { "Authorization": 'Bearer XXXXXX' }
});

存储cookie后,调用测试函数以使用HLS.js播放我的视频:

function test(){
  if (Hls.isSupported()) {
  var video = document.getElementById('video');
  var config = {
    debug: true,
    xhrSetup: function (xhr,url) {
        xhr.withCredentials = true; // do send cookie
    xhr.setRequestHeader("Access-Control-Allow-Headers","Content-Type, Accept, X-Requested-With");
        xhr.setRequestHeader("Access-Control-Allow-Origin","http://sybdomain.domain.com:8080");
    xhr.setRequestHeader("Access-Control-Allow-Credentials","true");
    }
  };
  var hls = new Hls(config);
  // bind them together
  hls.attachMedia(video);
  hls.on(Hls.Events.MEDIA_ATTACHED, function () {
    console.log("video and hls.js are now bound together !");
    hls.loadSource("http://cloudfrontDomain.net/small.m3u8");
    hls.on(Hls.Events.MANIFEST_PARSED, function (event, data) {
      console.log("manifest loaded, found " + data.levels.length + " quality level");
    });
  });
}
video.play();
}

如下所示,HLS OPTIONS和GET请求不设置会话cookie:

HLS OPTIONS请求:

OPTIONS /hls/98400738-a415-4e32-898c-9592d48d1ad7/small.m3u8 HTTP/1.1
Host: cloudfrontDomain.net
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: subdomain.mydomain.com:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.104 Safari/537.36
Access-Control-Request-Headers: access-control-allow-credentials,access-control-allow-headers,access-control-allow-origin
Accept: */*
Referer: http://subdomain.mydomain.com:8080/play.html
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8,es;q=0.6

CloudFront响应:

HTTP/1.1 200 OK
Content-Length: 0
Connection: keep-alive
Date: Fri, 07 Jul 2017 00:16:31 GMT
Access-Control-Allow-Origin: http://subdomain.mydomain.com:8080
Access-Control-Allow-Methods: GET, HEAD
Access-Control-Allow-Headers: access-control-allow-credentials, access-control-allow-headers, access-control-allow-origin
Access-Control-Max-Age: 3000
Access-Control-Allow-Credentials: true
Server: AmazonS3
Vary: Origin,Access-Control-Request-Headers,Access-Control-Request-Method
Age: 845
X-Cache: Hit from cloudfront
Via: 1.1 cloudfrontDomain.net (CloudFront)
X-Amz-Cf-Id: XXXXXX

HLS后续GET请求错过了cookie:

GET /hls/98400738-a415-4e32-898c-9592d48d1ad7/small.m3u8 HTTP/1.1
Host: cloudfrontDomain.net
Connection: keep-alive
Origin: http://subdomain.mydomain.com:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.104 Safari/537.36
Access-Control-Allow-Origin: http://subdomain.mydomain.com:8080
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Content-Type, Accept, X-Requested-With
Accept: */*
Referer: http://subdomain.mydomain.com:8080/play.html
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8,es;q=0.6

我花了4天的时间试图解决这个问题。我做了大量的研究,但我无法弄清楚解决方案。我是CORS的新手,所以也许我不理解某些原则。我想如果你在会话中存储了cookie,那么如果你使用凭证启用了xhr,它们就会被设置,但似乎并非如此。

我注意到的另一件事是HLS.js生成的GET请求没有设置任何xmlhttprequest标头。

感谢您的帮助:)

2 个答案:

答案 0 :(得分:2)

我终于能够让它发挥作用了。谢谢迈克尔的帮助!事实证明,它不是在理解CORS原理如何工作以及正确配置aws服务。主要问题是通过使用cloudfront同时为您的webservice和s3存储桶提供服务来避免跨域请求。我要添加的一个重要注意事项是,您在aws中所做的任何更改都必须等待它传播。作为一个新的aws dev我不知道并且非常沮丧地做出无效的改变。这是解决方案:

1)创建S3存储桶。

2)创建Cloudfront分发。

3)在分发集中设置为您的Web服务域的默认来源。

4)添加第二个源并在分发中添加一个行为,将所有.m3u8和.ts文件转发到S3存储桶。

5)添加存储桶来源时,请确保标记限制访问权限并更新存储桶策略复选框。

6)在您的存储桶分发行为中,请确保转发所有白名单标题和Cookie。这可以在aws控制台中设置。

7)如果您在服务中使用不同的端口,请确保在分发中也设置了这些端口。

8)转到S3存储桶设置并将CORS配置更新为以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>HEAD</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration> 

如果您正在使用HLS.js设置以下配置,那么这一点非常重要:

var config = {
debug: true,
xhrSetup: function (xhr,url) {
xhr.withCredentials = true; // do send cookie
xhr.setRequestHeader("Access-Control-Allow-Headers","Content-Type, Accept, X-Requested-With");
    xhr.setRequestHeader("Access-Control-Allow-Origin","http://sybdomain.domain.com:8080");
xhr.setRequestHeader("Access-Control-Allow-Credentials","true");
}
};
var hls = new Hls(config);

其他重要说明:

当您使用网络服务提供Cookie时,您可以将路径设置为&#34; /&#34;它将适用于您域中的所有请求。

答案 1 :(得分:0)

对于可能仅在 Android 版 Chrome 上遇到此问题的任何人,我们的问题是浏览器正在缓存 m3u8 文件并给出相同的 CORS 错误。解决方案是在文件 url 的查询字符串中附加一个时间戳参数:

var config = {
  xhrSetup: function (xhr, url) {
    xhr.withCredentials = true; // do send cookies
    url = url + '?t=' + new Date().getTime();
    xhr.open('GET', url, true);
  }
};
var hls = new Hls(config);