如何通过 Heroku/Node 配置简单的静态 AWS S3 映像读取.js (403 访问错误)



我一直在尝试为 AWS S3 存储桶配置读取权限,但没有成功。

我的用例:在 Node.js/express 上运行的私有应用程序,显示来自 S3 存储桶的静态徽标图像文件。存储在 S3 存储桶中的图像文件不应公开访问,并且只能提取以显示在我的应用程序的视图中。出于这个问题的目的,我实际上是在提供包含单个图像元素的单个 HTML 页面。

我遵循了本 Heroku 指南中的步骤,该指南建议如果您在 Heroku 的配置变量中设置有效的 AWS 密钥对(代表具有正确凭证的 AWS 角色(和 S3 存储桶名称,您应该只需能够将指向 S3 图像文件的链接插入到 HTML 中,它应该在网站上呈现。

到目前为止,我的大部分时间都在使用 S3 存储桶和我正在使用的 IAM 角色的 AWS 权限。

这是我到目前为止所做的:

  1. 在 AWS 上,我创建了一个名为"userx"的 IAM 用户,该用户具有"编程访问"(即生成的密钥对(。在用户创建期间,我通过"直接附加现有策略"设置权限,并将"AmazonS3FullAccess"策略附加到我的新用户。假设此用户的 ARN 为 "arn:aws:iam::12345:user/userx">

  2. 生成新用户(以及新的访问密钥 ID + 秘密访问密钥(后,我通过以下方式在终端窗口中更新我的 Heroku 配置:

    heroku config:set AWS_ACCESS_KEY_ID=123MYACCESSKEYID

其次:

heroku config:set AWS_SECRET_ACCESS_KEY=123MYSECRETKEYxyz
  1. 我创建了一个名为"my-assets"的 AWS S3 存储桶,并将权限设置为"不授予对此存储桶的公有读取访问权限"。我将单个图像文件上传到此存储桶:myimage.png。我通过生成新的存储桶策略并将其附加到存储桶来设置存储桶权限:

{
"Version": "2012-10-17",
"Id": "Policy1528038465156",
"Statement": [
{
"Sid": "Stmt1528038463415",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::12345:user/userx"
},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::my-assets",
"arn:aws:s3:::my-assets/*"
]
}
]
}

在 heroku 上,我通过以下方式设置存储桶名称:

heroku config:set S3_BUCKET_NAME=my-assets
  1. 我在存储桶上设置了 CORS 配置,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>

在 heroku 上,我重新启动我的服务器,并启动我的应用程序,该应用程序当前提供带有一个元素的单个 html 文件:

<<img src="https://s3.amazonaws.com/my-assets/myimage.png" />

在我的 chrome 终端中,当页面加载时,对 S3 存储桶的请求失败并显示 403 禁止错误。

我的理解是 - 对于获取静态文件的简单情况 - Heroku 应该处理对我的 S3 存储桶的 GET 请求,使用我加载到其配置变量中的密钥对对请求进行签名,并且由于 IAM、存储桶策略, 和上面给出的 CORS 配置。

我已经三重检查了我的密钥对等,我的想法是否正确,不需要做任何事情来配置从 heroku 到 AWS 的请求(即我不需要使用 AWS 开发工具包或类似的东西(?

这与 heroku 无关,heroku 没有提供您的文件,您直接从浏览器访问 s3。

如果要直接从 s3 提供文件,则必须授予这些文件公共读取权限。

要公开文件,只需:

click file > More > Make public

如果要从服务器从私有存储桶上传/读取文件,则需要访问密钥,但如果从浏览器请求托管在具有公有读取访问权限的 S3 中的图像,则不需要访问密钥。

关于您的 CORS 配置,您可以查看以下问题:

从 S3 下载图像时出现 cors 错误


如果要将文件保密,并且仅允许某些经过身份验证的用户查看它们,则可以使用aws-sdk生成签名的 S3 URL,并在浏览器上使用该 URL。

const AWS = require('aws-sdk')
const s3 = new AWS.S3()
AWS.config.update({ 
accessKeyId: 'keyId', 
secretAccessKey: 'accessKey'
})
const params = {
Bucket: 'bucket-name',
Key: 'my-assets/myimage.png',
Expires: 60 // Seconds
};
(async() => {
s3.getSignedUrl('getObject', params, (err, url) => {
console.log(url);
// This is the URL that you need to use on your HTML
});
})();

最新更新