如何配置AWS API Gateway仅接收CloudFront请求,无需认证
嘿,这个需求我之前帮朋友处理过,不用复杂的认证系统也能搞定,主要有两种靠谱的思路,都是利用AWS原生服务的特性,给你详细说下:
方案一:自定义请求头验证(最推荐,灵活且易维护)
这个方法的核心是让CloudFront在转发请求到API Gateway时带上一个只有你知道的自定义请求头,然后在API Gateway侧验证这个头的存在和正确性,不符合的直接拒绝。
具体步骤:
配置CloudFront添加自定义请求头
- 打开CloudFront控制台,找到你的分发,进入「行为」标签页,编辑对应的行为
- 在「缓存键和源请求」里,找到「自定义请求头」,点击「添加自定义头」
- 输入一个自定义的头名称(比如
X-CF-Allowed)和一个难猜测的密钥值(比如YourSuperSecretKey123!,别用太简单的字符串) - 保存修改,等待CloudFront部署完成(大概10-15分钟)
在API Gateway设置请求验证
有两种方式实现验证:方式A:API Gateway资源策略
直接给API Gateway添加资源策略,拒绝所有没有携带正确自定义头的请求。示例策略如下:{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": "execute-api:Invoke", "Resource": "arn:aws:execute-api:REGION:ACCOUNT_ID:API_ID/*/*/*", "Condition": { "StringEquals": { "aws:Request/X-CF-Allowed": "YourSuperSecretKey123!" } } }, { "Effect": "Deny", "Principal": "*", "Action": "execute-api:Invoke", "Resource": "arn:aws:execute-api:REGION:ACCOUNT_ID:API_ID/*/*/*", "Condition": { "Null": { "aws:Request/X-CF-Allowed": true } } } ] }记得把
REGION、ACCOUNT_ID、API_ID替换成你自己的信息,头名称和密钥要和CloudFront里的配置完全一致。方式B:Lambda请求验证(适合复杂逻辑场景)
如果以后需要更复杂的验证逻辑(比如结合时间戳防重放),可以创建一个轻量的Lambda函数,检查请求头是否符合要求,然后在API Gateway的「请求验证」模块关联这个Lambda。不过只是简单验证的话,资源策略就足够用了。
方案二:白名单CloudFront的IP地址范围
CloudFront会发布全球范围内的服务IP地址列表,你可以把这些IP添加到访问白名单里,只允许来自这些IP的请求访问API Gateway。
具体步骤:
获取CloudFront的IP范围
AWS官方会定期更新CloudFront的IP列表,你可以下载官方提供的IP范围文件,筛选出标记为service: CLOUDFRONT的条目。配置访问白名单
- 用AWS WAF(推荐,便于IP更新)
创建一个WAF Web ACL,添加「IP匹配」规则,将CloudFront的IP范围导入到白名单IP集中,然后把这个Web ACL关联到你的API Gateway。后续CloudFront IP更新时,只需要同步更新WAF的IP集即可。 - 用API Gateway资源策略
直接在资源策略里指定允许的IP范围,示例如下:
注意:CloudFront的IP范围数量较多,手动添加麻烦且需要定期更新,所以这种方式更适合临时场景,长期维护还是WAF更省心。{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": "execute-api:Invoke", "Resource": "arn:aws:execute-api:REGION:ACCOUNT_ID:API_ID/*/*/*", "Condition": { "IpAddress": { "aws:SourceIp": [ "192.0.2.0/24", "203.0.113.0/24" ] } } } ] }
- 用AWS WAF(推荐,便于IP更新)
测试验证
配置完成后,可以用Postman直接调用API Gateway的原始域名,应该会返回403 Forbidden;而通过CloudFront域名访问则能正常请求,这样就说明配置生效了。
内容的提问来源于stack exchange,提问作者user9538877

