【问题标题】:AWS S3 JavaScript browser upload without access key无需访问密钥的 AWS S3 JavaScript 浏览器上传
【发布时间】:2020-12-19 08:01:54
【问题描述】:

我想将文件上传到 S3,最好不要通过后端服务器,而只能通过浏览器。

在 AWS 示例中,要创建 S3 客户端,我需要提供密钥和密钥 ID:

const S3 = new AWS.S3({
    accessKeyId: <ACCESS_KEY_ID>,
    secretAccessKey: <ACCESS_KEY_SECRET>,
    region: <AWS_REGION>
});

但我不想公开我的访问密钥。该网站托管在 CloudFront 中,是否可以在 CloudFront 和 S3 存储桶之间设置权限,这样我就不需要在 JavaScript 中提供凭据?

【问题讨论】:

    标签: javascript amazon-web-services amazon-s3


    【解决方案1】:

    出于安全原因,您通常应该有一些方法来审核上传到 S3 的对象的来源(如果您允许公共访问,它毕竟可以是任何东西)。

    与其允许完全公开访问,不如设置AWS Cognito 并在您的前端使用它。

    您可以选择以下场景之一:

    • 用户通过认知用户登录
    • 使用匿名用户。

    这两个选项都会生成可供前端使用的临时凭据。这将防止用户记下它们并永久保留它们,确保您将权限锁定为仅针对该特定 S3 存储桶的 putObject。

    另一种方法是使用 API Gateway 和 Lambda 生成可支持上传的预签名 URL。有关此方法的更多信息,请查看this article

    为了增强您的安全性,可能值得添加一个S3 event 来触发一个 Lambda,该 Lambda 将在对象上传后对其进行验证。

    【讨论】:

    • 谢谢,克里斯。我已经尝试过 Cognito 并且它有效。我想改进一件事 - 目前,我正在使用未经身份验证的用户。我的应用程序正在使用 Okta,我创建了一个带有 OpenID 的身份池,没有用户池。但是当我用我的 id_token(从 Okta 返回)调用 CognitoIdentity.getId() 时,它会引发错误“登录令牌无效。无法验证签名令牌”。您过去是否遇到过此错误?
    • 嗯,我相信你应该返回一个访问密钥、密钥和一个会话 ID。您是否在请求中使用了所有三个?
    • 我在调用 getId() 时没有获得任何访问密钥。我按照他们的指示:docs.aws.amazon.com/cognitoidentity/latest/APIReference/…
    【解决方案2】:

    您需要某种后端才能有效地隐藏您的凭据。由于您已经在 AWS 世界中,您可以使用 AWS Lambda 函数将所谓的预签名上传 URL 返回到您的前端,您可以使用该 URL 上传二进制文件。

    更多信息: AWS S3 Presigned URLs

    【讨论】:

      【解决方案3】:

      您需要使用 S3 预签名 URL。您的后端会生成一个包含签名的特殊 URL,并将其发送到浏览器。然后浏览器可以使用该 URL 发送 POST 请求(或 PUT 请求,但这是一个签名的 PUT URL)以将文件直接上传到 S3 存储桶。没有访问密钥暴露给客户端。

      您仍然需要将访问密钥添加到您的后端,如果它位于 AWS 内部,则可以通过角色来添加。但是这些密钥不会到达浏览器,只会到达签名。

      我有大量的written about this topic,也有made code examples,你可以查看。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-01-31
        • 2019-04-22
        • 2020-09-18
        • 1970-01-01
        • 2016-05-23
        • 2013-08-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多