首页 > 解决方案 > 使用 CloudFront 函数将 X-Frame-Options 标头添加到所有 URL

问题描述

我有一个单页应用程序,我试图通过将 X-Frame-Options 标头添加到 HTML 响应来防止点击劫持。我的网站通过 CloudFront 托管在 S3 上。

CloudFront 分配配置为index.html默认发送:

Default root object
index.html

在错误页面部分,我将 404 页面配置为也指向index.html. 这样,所有不在 S3 中的 URL 都会返回默认的 HTML,即/login/admin等等。

404错误页面配置

更新还配置了403状态码: 403错误页面配置

然后我创建了一个 CloudFront 函数,如此处所述并将其分配给查看器响应:

function handler(event) {
    var response = event.response;
    var headers = response.headers;

    headers['x-frame-options'] = {value: 'DENY'}; 

    return response;
}

这有效,但仅适用于/

curl -v https://<MYSITE.com>
....
< x-frame-options: DENY

对于其他 URL,它不起作用 - 缺少 x-frame-options 标头:

curl -v https://<MYSITE.com>/login
....
< x-cache: Error from cloudfront

我的问题是 - 为什么我的 cloudfront 函数没有在错误响应中附加标头,我该怎么做才能添加它?

标签: amazon-web-servicesamazon-cloudfront

解决方案


我了解您的问题是:

  • Q1:为什么 CloudFront 功能适用于/
  • Q2:为什么 CloudFront 功能不适用于其他 url 路径?

请参考以下回复:

  • A1:因为您可能会指定一个Default Root Object [1](例如index.html),它在用户请求根 URL 时返回对象。当 CloudFront 返回带有 的对象时200 ok,将对viewer response事件调用 CloudFront 函数。
  • A2:您可能没有s3:ListBucket在您的 S3 存储桶策略中授予权限(例如OAI)。结果,您将收到 Access Denied(403) 丢失对象的错误,而不是 404 Not Found 错误。即,Error Pages您配置的 不适用于这种情况,并且不会调用 CloudFront 函数,因为 HTTP 状态码高于 399 [2]

[Updated]建议:

  • viewer response因为当源返回 HTTP 状态代码 400 或更高时,CloudFront 不会为事件调用边缘函数。origin response但是,会为所有源响应调用事件的Lambda@Edge 函数。在这个场景中,我建议我们应该使用 Lambda@Edge 而不是 CloudFront 函数。
  • 为方便起见,请参考l@e的示例代码:
exports.handler = async (event, context) => {
    const response = event.Records[0].cf.response;
    const headers = response.headers;
   
    headers['x-frame-options'] = [{
        key: 'X-Frame-Options',
        value: 'DENY',
    }];

    return response;
};
  • 供参考。这是我的卷曲测试结果:
# PATH: `/`
$ curl -sSL -D - https://dxxxxxxx.cloudfront.net/
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 12
Connection: keep-alive
ETag: "e59ff97941044f85df5297e1c302d260"
___snipped___
Server: AmazonS3
X-Frame-Options: DENY
___snipped___

# PATH: `/login`
$ curl -sSL -D - https://dxxxxxxx.cloudfront.net/login
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 12
Connection: keep-alive
ETag: "e59ff97941044f85df5297e1c302d260"
___snipped___
Server: AmazonS3
X-Frame-Options: DENY
___snipped___

推荐阅读