CloudFront 跨域问题(CORS)的几种解决方式

1. 背景说明

跨域资源共享是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其它 origin(域,协议和端口),使得浏览器允许访问这些 origin 加载的资源。为了让CORS请求能正常工作,浏览器通常会使用预检(Preflight)请求来验证服务端是否支持CORS。预检请求通常使用OPTIONS方法发起,请求中会包含真实请求中会用到的头和方法。

常见的CORS使用场景包括XMLHttpRequest发起api请求、加载CSS文件/字体文件等。在使用CloudFront对源站进行加速时,可能会为不同的资源/接口服务分配独立的域名。如果配置不当就比较容易出现跨域资源共享(CORS)错误,表现为浏览器报错无法加载静态资源或请求API接口。

本文将根据源站对CORS支持情况及客户端需求,介绍几种CloudFront CORS错误的解决方式。

2. 解决CloudFront跨域资源共享问题的几种方式

2.1 CloudFront配置前置条件

如之前所述,浏览器会通过预检请求来确认站点是否支持CORS,而预检通常使用OPIONS方法,因此首先要确保CloudFront能够支持OPTIONS方法,示例配置如下:

配置项 可选值
自动压缩对象 No / Yes
查看器协议策略 HTTP and HTTPS / Redirect HTTP to HTTPS / HTTPS only
允许的HTTP方法 GET, HEAD;GET, HEAD, OPTIONS(结合实际需要,选择包含OPTIONS的选项);GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
缓存HTTP方法 默认情况下,将会缓存GET和HEAD方法

2.1 使用源请求策略

若CloudFront源站本身支持CORS,则可通过配置源请求策略来使得CloudFront支持CORS。源请求策略应包含如下标头:

  • Origin,下拉框选择
  • Access-Control-Request-Method,自定义方式添加
  • Access-Control-Request-Headers,自定义方式添加
详细配置信息
  1. 名称:为origin request输入名称,示例:CachePolicySupportCORS
  2. 说明-可选:为origin request输入描述,示例:CachePolicySupportCORS
  3. 源请求设置信息:
    • 标题:选择要包括在源请求中的标头,选择包括以下标题
    • 添加标头:选择现有标题元素或者创建自定义标题(最多10),依次添加Origin、Access-Control-Request-Headers、Access-Control-Request-Method

配置完成后,更改CloudFront行为,使用新创建的源请求策略。

注意:为简化操作,也可以直接使用托管的源请求策略 Managed-CORS-S3Origin

2.2 使用源响应头策略

除源请求策略、缓存策略之外,亚马逊云科技在2021年为CloudFront添加了响应头策略(Response header policy),以便客户方便的修改返回给客户端的响应头。可使用默认的响应头策略或者根据需要自建。

相关配置项
  • 缓存键和源请求:建议使用缓存策略和源请求策略来控制缓存键和源请求,可选Cache policy and origin request policy (recommended)Legacy cache settings
  • 缓存策略:选择现有缓存策略或创建新的缓存策略,如CachingOptimized、Default policy when CF compression is enabled
  • 源请求策略-可选:选择现有源请求策略或创建新的源请求策略
  • 响应标头策略-可选:选择现有的响应标头策略或创建一个新的响应标头策略,如SimpleCORS(Allows all origins for simple CORS requests)

注意:CloudFront Behavior配置响应头策略之后,需要在请求中带上Origin标头CloudFront才会返回CORS相关Header。

测试示例
bash 复制代码
liyxmse@3c22fb76243a ~% curl -I -H "Accept: image/png" https://d2ppuuhvlo93jy.cloudfront.net/download.png
HTTP/2 200
content-type: image/png
content-length: 99866
date: Tue, 12 Apr 2022 16:24:40 GMT
last-modified: Thu, 07 Apr 2022 09:44:15 GMT
etag: "cac8758fcbf17dbe1b870e828d85b7a2"
accept-ranges: bytes
server: AmazonS3
vary: Origin
x-cache: Hit from cloudfront
via: 1.1 933f4fb3c49c9a37f5b5461deacd212c.cloudfront.net (CloudFront)
x-amz-cf-pop: HKG60-C1
x-amz-cf-id: 6iqbH3ItfJ-PxtwcMWR3L4Sy8tBtmUjRrytr5z_Qe8PVLMxpsaPbA==
age:127

liyxmse@3c22fb76243a ~% curl -I -H "Origin: https://exam.com" https://d2ppuuhvlo93jy.cloudfront.net/download.png
HTTP/2 200
content-type: image/png
content-length: 99866
date: Tue, 12 Apr 2022 16:24:12 GMT
Last-modified: Thu, 07 Apr 2022 09:44:15 GMT
etag: "cac8758fcbf17dbe1b870e828d85b7a2"
accept-ranges:bytes
server: AmazonS3
access-control-allow-origin:
x-cache: Hit from cloudfront
via: 1.1 f7d57a4f9ccb4dee501ecb0c0d07fab4.cloudfront.net (CloudFront)
x-amz-cf-pop: HKG60-C1
x-amz-cf-id: TrYa_82j2KYGE2xPZ1JFhD1gXCP8Jkbu6RNyhZmvn1s0dikY6TTw7Q==
age:150

2.3 使用CloudFront Function

某些情况下(比如H5游戏),客户端期望站点的返回中一直包含CORS相关的标头,此时使用前文提到的方法将失效。为使CloudFront固定返回CORS相关标头,需要使用CloudFront Function功能。

原理是在边缘节点返回结果给客户端之前,通过边缘节点上执行一段代码更改返回结果的标头。

CloudFront样例代码
javascript 复制代码
function handler(event)  {
    var response  = event.response;
    var headers  = response.headers;

    // If Access-Control-Allow-Origin CORS header is missing, add it.
    // Since JavaScript doesn't allow for hyphens in variable names, we use the dict["key"] notation.
    if (!headers['access-control-allow-origin']) {
        headers['access-control-allow-origin'] = {value: "*"};
        console.log("Access-Control-Allow-Origin was missing, adding it now.");
        headers['access-control-allow-headers'] = {value: "Origin, X-Requested-With, Content-Type, Accept"};
        headers['access-control-allow-methods'] = {value: "GET,POST,PUT, OPTIONS"};
    }

    return response;
}
配置方式

CloudFront 行为配置如下,其中ForceCORSHeaders为CloudFront Function名称:

  • 响应标头策略-可选:选择现有的响应标头策略或创建一个新的响应标头策略
  • 函数关联-可选信息:选择要与此缓存行为关联的Edge函数,以及调用此函数的CloudFront事件
    • 函数类型:CloudFront Function
    • 绑定事件:查看器响应
    • 函数ARN/名称:ForceCORSHeaders
    • 包括正文:无关联

借助CloudFront Function的边缘计算能力,还可以实现边缘鉴权、AB测试等功能。

3. 总结

本文介绍了3种解决CloudFront CORS错误的方法,对比如下:

方法 使用难度 成本 特点
源请求策略 一般 无额外成本 需要源站支持CORS
响应头策略 简单 无额外成本 配置简单
CloudFront Function 较难 会产生额外成本,提供免费额度 需要编写代码,功能灵活

选型建议

  • 如果需要快速让CloudFront支持CORS,比较方便的方式是使用响应头策略;
  • 如果需要CloudFront一直返回CORS标头信息或需要支持其他个性化标头/需求,则可以使用CloudFront Function。

4. 参考资料

  1. https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS
  2. https://aws.amazon.com/cn/blogs/networking-and-content-delivery/amazon-cloudfront-introduces-response-headers-policies/
  3. https://aws.amazon.com/premiumsupport/knowledge-center/no-access-control-allow-origin-error/
  4. https://aws.amazon.com/cn/blogs/china/several-solutions-to-cloudfront-cross-domain-problem-cors/
相关推荐
IMPYLH2 小时前
Linux 的 install 命令
linux·运维·服务器·bash
寻道模式2 小时前
【运维心得】“龙虾”非本地访问的坑
运维·服务器
浦信仿真大讲堂2 小时前
CST FAQ 006:Linux系统CST安装指导
linux·运维·服务器·仿真软件·达索软件
HABuo3 小时前
【linux线程(三)】生产者消费者模型(条件变量阻塞队列版本、信号量环形队列版本)详细剖析
linux·运维·服务器·c语言·c++·ubuntu·centos
运维行者_3 小时前
使用 Applications Manager 实现 AWS 云监控:保障业务应用高效运行
大数据·运维·服务器·网络·数据库·云计算·aws
安科士andxe3 小时前
深度解析|安科士100G QSFP28 30km光模块核心技术,破解中长距传输痛点
运维·服务器·网络
Java面试题总结3 小时前
Linux根分区爆满(占用81%)排查与解决实战
linux·运维·服务器
想要入门的程序猿4 小时前
VTK与PCL源码编译(Ubuntu 20.04.6)
linux·运维·服务器
EmbeddedCore4 小时前
轻量级消息防重模块全解析:从原理到高性能优化
linux·运维·服务器·嵌入式硬件