我已经创建了以下 CloudFront Origin 请求策略:
我需要Authorization
标头(没有Authorization
标头则AntiForgeryToken
标头不会被转发)但我不明白为什么 CloudFront 不允许将Authorization
标头添加到策略中?
我收到以下错误:
400 参数 Headers 包含不允许的授权。
我已经关注这个文件并将Authorization
标头添加到缓存策略,但仍然无法AntiForgeryToken
在我的请求中获取...
如果我使用旧版缓存策略(而不是创建自己的自定义策略),那么我能够将授权标头列入白名单但不知道为什么我不能在我自己的自定义策略中做到这一点?
答案1
这也让我感到困惑,查询字符串和标头都如此,例如Authorization
。
但是,文档指出要将标题传递到原点,必须将其用作缓存键:
缓存键设置指定 CloudFront 在缓存键中包含的查看器请求中的值。这些值可以包括 URL 查询字符串、HTTP 标头和 Cookie。包含在缓存键中的值会自动包含在 CloudFront 发送到源的请求(称为源请求)中。
和
注意:您不能使用源请求策略来转发授权标头。标头必须是缓存键的一部分,以防止缓存满足未经授权的请求。如果您尝试创建转发授权标头的源请求策略,CloudFront 将返回 HTTP 400 错误。
此外,请注意,与来源请求策略相关Managed-AllViewer
,问题似乎是将Host
标头转发到 API 网关;请参阅https://github.com/aws-cloudformation/cloudformation-coverage-roadmap/issues/571#issuecomment-792051286即我们不能将其用于Managed-AllViewer
API 网关来源。
看
- https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/controlling-the-cache-key.html
- https://aws.amazon.com/premiumsupport/knowledge-center/cloudfront-authorization-header/
作为 CDKcloudfront.Distribution()
构造的一部分:
const apiCachePolicy = new cloudfront.CachePolicy(this, 'ApiCachePolicy', {
headerBehavior: cloudfront.CacheHeaderBehavior.allowList('authorization'),
queryStringBehavior: cloudfront.CacheQueryStringBehavior.all(),
cookieBehavior: cloudfront.CacheCookieBehavior.none(),
minTtl: Duration.minutes(0),
maxTtl: Duration.minutes(1),
defaultTtl: Duration.minutes(0),
enableAcceptEncodingGzip: true,
enableAcceptEncodingBrotli: true,
});
答案2
可以使用 Origin 请求策略转发所有标头(使用 Managed-AllViewer),其中包括授权。如上所述,这确实会导致与 API 网关发生冲突,因为 HOST 标头与请求不匹配(请求来自 CloudFront,HOST 来自用户),因此 API 网关将返回 403。为了解决这个问题,您可以部署 Lambda@Edge 函数来重写 HOST 标头以匹配 CloudFront。然后 API 网关将接受该请求。
为此,在 US-EAST-1 中创建一个 Lambda 函数(必须在此处进行复制,添加edgelambda.amazonaws.com
到 Lambda 角色上的受信任实体,然后向 Lambda 函数添加一个 CloudFront 触发器以进行原始请求并指定您想要使用它的分发。
以下是 Node.JS 中执行该任务的示例 Lambda@Edge 函数:
'use strict';
exports.handler = (event, context, callback) => {
const request = event.Records[0].cf.request;
/* Set host header to API GW domain*/
request.headers['host'] = [{ key: 'host', value: request.origin.custom.domainName }];
console.log('successfully executed Lambda at Edge')
callback(null, request);
};