亚马逊AWS官方博客

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方法,示例配置如下。

2.1. 使用源请求策略

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

  • Origin,下拉框选择
  • Access-Control-Request-Method,自定义方式添加
  • Access-Control-Request-Headers,自定义方式添加

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

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

2.2 使用源响应头策略

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

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

2.3 使用CloudFront Function

某些情况下(比如H5游戏),客户端期望站点的返回中一直包含CORS相关的标头,此时使用前文提到的方法将失效。为使CloudFront固定返回CORS相关标头,需要使用CloudFront Function功能。原理是在边缘节点返回结果给客户端之前,通过边缘节点上执行一段代码更改返回结果的标头。CloudFront样例代码如下:

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名称。

借助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/

本篇作者

李寅祥

AWS 解决方案架构师