使用安全Cookie从Cloudfront拒绝访问不会返回任何CORS标头,从而阻止从XHR请求中读取错误信息

时间:2018-04-08 03:11:26

标签: amazon-web-services amazon-s3 amazon-cloudfront

我正在使用云端安全Cookie来保护某些文件的私密性。当cookie auth成功并且原点被命中时,cloudfront将从原点返回正确的cors头(Access-Control-Allow-Origin)但是如何在403 / Access Denied期间使cloudfront返回CORS头?在对源的请求之前,此验证完全在cloudfront中,但是是否有启用它的设置?我希望能够向Cloudfront发出XHR请求并知道请求失败的原因。由于cloudfront不会在403上返回cors标头,因此大多数现代浏览器都会阻止读取请求中包含状态代码的任何信息,并且难以确定请求失败的原因。

谢谢!

1 个答案:

答案 0 :(得分:2)

如您所知,CloudFront不会自发地发出CORS标头 - 它们需要来自原始服务器 - 因此,为了在响应中查看CORS标头,CloudFront需要允许该请求。但是,当然,它是不允许的,因为你试图捕获的条件是403 Forbidden

因此,我们需要的是为了让您的未经授权的响应对CORS友好,这是另一个来源,它可以为我们提供备用错误响应,并且该来源需要具有CORS感知能力。解决方案似乎是我们可以通过CloudFront Custom Error Responses的一些帮助以及为此目的而创建的其他空S3桶来完成的。

自定义错误响应允许您配置CloudFront以从其他来源获取自定义错误响应,而不是在内部生成它。作为该过程的一部分,原始请求中的一些标头包含在上游提取中,并返回错误文档中的响应标头。

S3是一个方便的起源,因为它具有可配置的CORS支持。

  • 创建一个新的空桶。
  • 为存储桶启用CORS,并使用适当的参数配置CORS。为此,默认配置可能没问题。
  • 创建一个CloudFront分配将使用的简单文件,而不是403的内置响应。出于测试目的,这可能只是一个文本文件,表示"访问被拒绝。"
  • 使用您喜欢的任何名称将文件上传到存储桶,例如403.txt。选择使对象可公开读取的选项。设置元数据Cache-Control: no-cache, no-store, private, must-revalidateContent-Type: text/plain(或text/html,具体取决于您在错误文件中的确切位置。)
  • 在CloudFront中,创建一个新的Origin。对于Origin Domain Name,从桶列表中选择存储桶。
  • 创建一个新的缓存行为,匹配路径/403.txt(或任何您命名的文件)。将OriginAccess-Control-Request-HeadersAccess-Control-Request-Method标头列入白名单以进行转发。将限制查看者访问权限设置为否,因为对于这一条路径,我们不需要签名凭据。请注意,此路径必须与存储桶中的文件名完全相同(前导斜杠除外,它不会显示在存储桶中,但应包含在此处)。
  • 在CloudFront自定义错误响应中,选择“创建自定义错误响应”。选择错误代码403,将Error Caching Minimum TTL设置为0,选择Customize Error Response Yes,设置Response Page Path /403.txt并将HTTP Response代码设置为403。
  • 利润!

测试:

$ curl -v dzczcnnnnexample.cloudfront.net -H 'Origin: http://example.com'
* Rebuilt URL to: dzczcnnnnexample.cloudfront.net/
*   Trying 203.0.113.208...
* Connected to dzczcnnnnexample.cloudfront.net (203.0.113.208) port 80 (#0)
> GET / HTTP/1.1
> Host: dzczcnnnnexample.cloudfront.net
> User-Agent: curl/7.47.0
> Accept: */*
> Origin: http://example.com
>
< HTTP/1.1 403 Forbidden
< Content-Type: text/plain
< Content-Length: 16
< Connection: keep-alive
< Date: Sun, 08 Apr 2018 14:01:25 GMT
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: GET, HEAD
< Access-Control-Max-Age: 3000
< Last-Modified: Sun, 08 Apr 2018 13:29:19 GMT
< ETag: "fd9e8f7be7b65381c4acc272b6afc858"
< x-amz-server-side-encryption: AES256
< Cache-Control: private, no-cache, no-store, must-revalidate
< Accept-Ranges: bytes
< Server: AmazonS3
< Vary: Origin,Access-Control-Request-Headers,Access-Control-Request-Method
< X-Cache: Error from cloudfront
< Via: 1.1 1234567890a26beddeac6bfc77b2d348.cloudfront.net (CloudFront)
< X-Amz-Cf-Id: ExAmPlEIbQBtaqExamPLEQs4VwcxhvtU1YXBi47uUzUgami0Hj0MwQ==
<
Access denied.
* Connection #0 to host dzczcnnnnexample.cloudfront.net left intact

在这里,Access denied.是我在我创建的文本文件中放置的内容。在确认这对您有用之后,您可能希望获得更多创意,就像它对我一样。每当CloudFront抛出403错误时,将始终返回S3中此新文件的内容。此外,只要您的来源抛出403,它也会被返回,因为自定义错误响应旨在用给定的HTTP状态代码替换所有错误。

您在上面注意到我们看到Access-Control-Allow-Origin: *。这是S3 CORS的默认行为。如果您在S3 CORS配置中提供明确的来源,则会得到这样的响应......

Access-Control-Allow-Origin: http://example.com

...但是对于GET请求,我认为这种特殊性不是必需的,并且通配符就足够了。此处描述的方案不是为整个CloudFront分配设置CORS - 仅用于错误响应。