我有一个使用 Vercel 部署的 Next.js 应用程序,并使用 AWS S3 存储桶来存储我希望只能从我的网站读取的照片。
我的 CORS 策略设置为允许所有流量,因此它不会影响任何内容:
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"GET",
"POST",
"PUT",
"DELETE"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": [],
"MaxAgeSeconds": 3000
}
]
这是我的桶政策:
{
"Sid": "AllowReadFromWebsite",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*",
"Condition": {
"StringLike": {
"aws:Referer": [
"https://my-domain.vercel.app/*",
"https://my-domain.vercel.app/_next/image*"
]
}
}
}
此策略不适用于生产环境中的 Next.js Image 标签。我不知道它到底是如何工作的,但我认为查看图像的请求不是直接来自我的网站域,而是以某种方式使用服务器或带有缓存的东西。如果我使用 img 标签,它就可以正常工作。另外,如果我将 http://localhost:3000 添加到存储桶策略并在开发中使用它,它可以与图像和 img 标签一起使用。我不知道问题是出在 Next.js Image 标签上还是出在 Vercel 上或者什么上。也许这与无服务器有关。有人对这个有经验么?我最终希望存储在存储桶中的照片只能从我的网站上读取。如何使用 Next.js Image 标签实现此目的?现在我正在使用:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowReadFromAnywhere",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*"
}
]
}
这是不明智的吗?我不太关心安全性,我只是不希望人们能够恶意地使用我的带宽。
推荐:
有关详细信息和参考,请参阅长部分。
在不了解有关 NextJS 设置的详细信息的情况下,我可以想象问题出在服务器端渲染、图像标签和/或 vercel 的工作方式上。您可以在 S3 存储桶中启用访问日志记录来排查存储桶的访问问题。
此外,S3 不支持 HTTPS。这意味着,如果您的网站“混合了不安全的 HTTP 请求和 HTTPS”,则浏览器可能会阻止对您的图像的请求。您可以设置 AWS CloudFront 以通过 HTTPS 提供来自 S3 的资产并缓存资产。 如果我理解正确的话,速率限制是您控制滥用的要求的一个选项。 对于此用例,我建议使用 AWS S3 和 AWS CloudFront 设置
静态文件托管(包括缓存),并受AWS Web 应用程序防火墙速率限制保护。 请注意微调 AWS WAF 和成本(尤其是 WAF)。 旁注:伪造任何 HTTP 标头都很简单,存在伪造的引荐来源网址工具。不要依赖这种安全级别。 即使您的照片只能通过您的网站访问,攻击者也可以简单地无休止地重新加载您的网站。
顺便说一句,我有一个非常相似的设置,但我仅使用 AWS 资源:使用 AWS Lambda 函数而不是 vercel 进行服务器端渲染,在 AWS S3 中托管静态内容,AWS CloudFront 作为 CDN。但我的 S3 Bucket 不是公开的。 描述如何设置超出了此处的范围,但请查看本指南使用 AWS 无服务器应用程序模型将 Nextjs 13 应用程序部署到 AWS Lambda
或查找类似指南。