我们正在尝试将一些自定义标头放入我们的云源分布中,但它没有按预期工作。以下是场景。
我们有一个名为“example-images”的 s3 存储桶,其中包含所有静态内容,s3 存储桶可供公众访问。具有以下 CORS 策略
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<ExposeHeader>Access-Control-Allow-Credentials</ExposeHeader>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
我们可以使用 curl 根据示例输出通过 URL 访问 s3 内容。
x-amz-id-2: xxxxxxxxxxxx
x-amz-request-id: xxxxxxxxxxxx
Date: Wed, 05 Oct 2016 04:10:26 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
Access-Control-Expose-Headers: Access-Control-Allow-Credentials
Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
Last-Modified: Mon, 26 Sep 2016 13:12:58 GMT
ETag: "xxxxxxxxxxxxxx"
Accept-Ranges: bytes
Content-Type: image/png
Content-Length: 1630
Server: AmazonS3
然后我们创建了一个云端分布来提供这些内容。
根据文档,我们在“默认来源”中设置了以下值
- 限制存储桶访问 = 否
原始自定义标题 一些自定义标题
例如“访问控制允许凭据 = true”
在 CF 分布“行为”中我们有以下设置。
- 协议策略 = http & https
- 允许 http 方法 = GET、HEAD、OPTIONS。
- 转发标头 = 白名单
- 白名单标头 = 来源
- 对象缓存 = 使用原始缓存标头
使用 CF Distribution URL 时我们仍然无法查看自定义标头。
curl -sI -H "Origin: example.com" -H "Access-Control-Request-Method: GET" -H "Access-Control-Allow-Credentials: GET"
HTTP/1.1 200 OK
Content-Type: image/png
Content-Length: 1630
Connection: keep-alive
Date: Wed, 05 Oct 2016 04:03:20 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
Access-Control-Expose-Headers: Access-Control-Allow-Credentials
Last-Modified: Mon, 26 Sep 2016 13:12:58 GMT
ETag: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Accept-Ranges: bytes
Server: AmazonS3
Vary: Origin
Age: 1231
X-Cache: Hit from cloudfront
Via: 1.1 xxxxxxxx.cloudfront.net (CloudFront)
X-Amz-Cf-Id: xxxxxxxxxxxxxxxxxxxxx
您能帮助我们找出这里缺少什么设置吗?
答案1
您可以使用以下方式向 CloudFront/S3 的响应添加自定义标头:Lambda@Edge函数。lambda 代码在本地边缘位置内运行,但需要在us-east-1
区域中创建和维护。
这里的示例代码使用 nodeJS 6.10 添加x-frame-options
响应标头,但你可以添加任何不是受限制的由 AWS 提供。
'use strict';
exports.handler = (event, context, callback) => {
const response = event.Records[0].cf.response;
const headers = response.headers;
response.headers['x-frame-options'] = [{"key":"X-Frame-Options","value":"SAMEORIGIN"}];
console.log(response.headers);
callback(null, response);
};
创建 Lambda 的最终版本,然后将 Lambda 版本的触发器配置设置为origin-response
路径模式行为的 CloudFront 事件类型。
示例代码将事件记录到 CloudWatch 日志服务中以供调试。如果您还没有,则需要设置一个 lambda 执行 IAM 角色,该角色允许允许 CloudWatch 日志操作由edgelambda.amazonaws.com
和承担的策略lambda.amazonaws.com
。
允许将日志写入 CloudWatch 的基本 Lambda 执行策略:
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*",
"Effect": "Allow"
}
]
}
信任关系允许 Lambda 和 Lambda@Edge 承担角色:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"edgelambda.amazonaws.com",
"lambda.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
如果 AWS 只是允许使用 CloudFront GUI 设置自定义标头,那就更好了,但在此之前,该解决方案应该可以满足您的要求。
答案2
我刚刚在查看器响应中实现了标头操作。它只是向 CloudFront 发送的响应添加标头。
您需要使用名为“CloudFront Function”的新工具。 https://console.aws.amazon.com/cloudfront/v3/home#/functions/ 直接在CDN的218+PoP上运行,而不只是在区域PoP上运行,函数需要用JS编写。
以下是 AWS 博客文章,比较了 lambda@edge 和 CloudFront 函数:https://aws.amazon.com/blogs/aws/introducing-cloudfront-functions-run-your-code-at-the-edge-with-low-latency-at-any-scale/
从 AWS 博客文章来看,最常见的用例是:
- HTTP 标头操作
- 缓存键操作和规范化
- URL 重写和重定向
- 访问授权
我的功能很简单:
function handler(event) {
var response = event.response;
var headers = response.headers;
// Set custom header
headers['custom-header'] = {value: '*'};
// Return the response to viewers
return response;
}
您所要做的只是将其附加到您的发行版,它就可以工作了。