Cookies hls.js CORS使用AWS Cloudfront解决cookie问题

Cookies hls.js CORS使用AWS Cloudfront解决cookie问题,cookies,xmlhttprequest,cors,amazon-cloudfront,hls.js,Cookies,Xmlhttprequest,Cors,Amazon Cloudfront,Hls.js,我正在尝试使用Cloudfront HLS功能设置视频流,但在请求中让HLS.js发送凭据cookie时遇到问题 我已经将Cloudfront配置为转发cookie和转发访问控制头。我还设置了S3 CORS策略,包括GET、HEAD 我遇到的问题是,即使我将xhr.withCredentials设置为true,并且在会话中定义了cookies,但当我使用chrome控制台查看请求时,我可以看到HLS请求没有cookies。结果,我从cloudfront得到一个错误响应,说我需要包括凭证cooki

我正在尝试使用Cloudfront HLS功能设置视频流,但在请求中让HLS.js发送凭据cookie时遇到问题

我已经将Cloudfront配置为转发cookie和转发访问控制头。我还设置了S3 CORS策略,包括GET、HEAD

我遇到的问题是,即使我将xhr.withCredentials设置为true,并且在会话中定义了cookies,但当我使用chrome控制台查看请求时,我可以看到HLS请求没有cookies。结果,我从cloudfront得到一个错误响应,说我需要包括凭证cookie

代码: 首先,我向我的服务器发出ajax请求以生成cookies。服务器返回三个集Cookie标头,这些标头存储为浏览器中的会话Cookie:

$.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选项和GET请求不设置会话cookie:

HLS选项请求:

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
云端响应:

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头


谢谢你的帮助:)

我终于可以让它工作了。谢谢迈克尔的帮助!事实证明,这是一个不理解CORS原理如何工作和正确配置aws服务的混合体。主要问题是通过使用cloudfront为您的Web服务和s3 bucket提供服务来避免跨域请求。我想补充的一个重要注意事项是,您在aws中所做的任何更改都必须等待它传播。作为一名新的aws开发人员,我不知道这一点,并且对做出没有效果的更改感到非常沮丧。以下是解决方案:

1) 创建S3存储桶

2) 创建Cloudfront发行版

3) 在分发集中,作为web服务域的默认源

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

5) 添加bucket origin时,请确保标记“限制访问”并同时更新bucket策略复选框

6) 在bucket分发行为中,确保转发所有白名单头和cookie。这些都可以在aws控制台中设置

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

8) 转到S3 bucket设置并将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> 
其他重要说明:


当您使用web服务提供cookie时,您可以将路径设置为“/”,它将应用于您域中的所有请求。

对于仅在Chrome For Android上出现此问题的任何人,我们的问题是浏览器正在缓存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);

来自example.com页面的XHR请求向example.net发送带有凭据的跨源请求,将发送example.net先前返回的cookies,而不是example.com返回的cookies。因此,我在这里面临一个两难选择。我的Web服务使用amazon aws生成cookies。问题是Web服务正在另一个域中运行。这意味着除非cloudfront域返回设置的cookie头,否则我不能将任何cookie传递给我的CORS请求?我不认为云前端支持生成cookie作为基于固定策略的响应的一部分。。。有什么想法或建议吗?在CloudFront中创建第二个源,将web服务作为源主机名,并创建一个缓存行为,其中包含指向该新源的服务路由路径。获取cookie的请求发送到CloudFront,CloudFront将其发送到源站获取cookie,cookie的响应通过CloudFront返回,并且它们被设置在正确的域上。这在原则上是可行的。它是否适用于您的服务?计划B.创建
sub.subdomain.example.com
,指向CloudFront。使用
domain=.subdomain.example.com
设置来自
subdomain.example.com
的cookie,注意前导点。当您向
sub.subdomain.example.com
发送请求时,这些cookie应该可以工作。谢谢!计划B的工作原理与中相同,现在发送cookies。但是现在CloudFront只是简单地拒绝来自我新的sub.subdomain.example.com的任何请求AccessDeniedAccessDenied我检查了我的s3存储桶及其允许http://*https://*的设置嘿,伙计,我面临着同样的问题,我在过去几天一直在这个问题上挣扎。你能解释一下第4步、第5步和第6步吗?因为我是AWS的初学者?提前准备好。
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);