如何安全地访问私人S3存储桶
#aws #javascript #react #devops

阅读更多类似的文章,visit my blog

将文件上传到远程服务器是任何现代应用程序中最常见的任务之一。 AWS拥​​有一个名为S3(简单存储服务)的服务,这使这项工作非常容易。

但是您知道我们如何安全地访问水桶?

好吧,今天我们将看到我们如何安全地执行最常见的2个操作

  1. 上传文件到S3

  2. 下载来自S3

  3. 的文件

让我们从上传文件开始。

第一件事首先

我假设您已经知道如何创建S3存储桶。如果没有大量文章。

您可以从已经拥有的任何存储桶开始,然后执行以下

转到 bucket - > 权限 - > 阻止所有公共访问

Block All Public Access

现在,我们的水桶已安全。现在,当任何人试图访问存储桶时,他们会看到它而不是实际文件。

Access denied

好吧,现在我们已经确保了水桶。但是我们需要正确访问吗?

让我们从如何将文件上传到存储桶开始。

选项1.通过自定义后端上传

您可以将文件发送到某种服务器,然后进行验证,然后使用正确的身份验证令牌将文件发送到S3并将URL返回给用户。

流程看起来像这样,

Frontend Application-> Custom Backend-> S3 Bucket

这种方法问题

  • 它增加了您的服务器上的负载。

  • 用户首先必须等待将文件上传到服务器,然后到S3,这需要时间。

  • 对于大型文件,有多个故障点是不可取的。

选项2.直接从前端上传

您可以将文件直接上传到远程服务器。这样,我们必须等待更少的时间。

Frontend Application-> S3 Bucket

以下文章显示了如何做。

How to Upload Files to AWS S3 in React
*In 2 different ways*javascript.plainenglish.io

这种方法的问题

  • 您必须直接在前端代码中存储安全令牌,这永远不是一个好主意。

  • 如果您的安全令牌被暴露了,可能会花费很多钱。

改进的解决方案:预签名的URL方法

现在,我们将看到我们如何才能解决前两种方法的所有问题。在这种方法中,我们可以使用我们的aws-sdk来生成预先签名的URL,以便我们可以直接访问S3存储桶而无需公开安全令牌。

首先,我们从前端发送有关对象的一些信息(不是实际文件)到某种后端API(可以是lambda函数)。

此功能获取信息并为我们创建帖子API。

然后,我们可以使用axiosfetch直接从前端发送对象。

这种方法的好处

  • 我们不需要在前端代码中存储任何类型的秘密

  • 我们不需要等待将实际文件发送到后端,从而将响应时间减少了 50%!

步骤1.准备后端

这是您可以用来生成签名URL
的功能

import AWS from 'aws-sdk'

AWS.config.update({
    accessKeyId: 'YOUR_ACCESS_KEY_ID',
    secretAccessKey: 'YOUR_SECRET_ACCESS_KEY',
})

const S3_BUCKET ='YOUR_BUCKET_NAME';
const REGION ='YOUR_REGION';
const URL_EXPIRATION_TIME = 60; // in seconds

const myBucket = new AWS.S3({
    params: { Bucket: S3_BUCKET},
    region: REGION,
})

function generatePreSignedPutUrl( fileName , fileType) {
    myBucket.getSignedUrl('putObject', {
        Key: fileName,
        ContentType: fileType,
        Expires: URL_EXPIRATION_TIME
    } , (err , url) => {
        return url // API Response Here
    });
}

您可以将此功能保留在lambda或您自己的后端。

步骤2.前端使用

在您的前端,您只需致电此API或lambda,然后将URL恢复,然后向您提供的端点提出一个简单的PUT请求。

有效载荷必须是您的实际文件,而不是某种多部分数据。

这是一个简单的反应组件,可以执行此操作

import React ,{useState} from 'react';

const UploadImageToS3 = () => {

    const [selectedFile, setSelectedFile] = useState(null);

    const handleFileInput = (e) => setSelectedFile(e.target.files[0]);

    const uploadFile = (file) => {

        const requestObject = {
            method:'POST' ,
            body:{
                fileName: file.name ,
                fileType: file.type
            }
        }

        fetch('YOUR_BACKEND_ENDPOINT',requestObject)
            .then(res => {
            fetch(res.signedUrl , {
                method:'PUT',
                body :file
            }).then((res) => {
                // DO WHATEVER YOU WANT
            })
        })

    }


    return <>
        <input type="file" onChange={handleFileInput}/>
        <button onClick={() => uploadFile(selectedFile)}> Upload to S3</button>
    </>
}

export default UploadImageToS3;

此组件可用于安全地上传文件。

安全地获取对象

我们已经看到了如何通过预先签名的URL安全地上传文件。那下载呢?

好吧,这里我们可以再次使用此预先签名的URL方法!现在,我们需要的是getObject型预先签名的URL,而不是putObject类型URL。我们可以使用以下功能来实现这一目标。

function generatePreSignedGetUrl( fileName , fileType) {
    myBucket.getSignedUrl('getObject', {
        Key: fileName,
        ContentType: fileType,
        Expires: URL_EXPIRATION_TIME
    } , (err , url) => {
        return url // API Response Here
    });
}

现在,每当我们的用户需要查看某些图像时,我们都会以预先签名的URL 而不是实际URL

就是这样!我希望这篇文章可以阐明如何安全访问 s3桶用于上传和下载数据。

过得愉快!

有话要说?

通过LinkedIn或我的Personal Website与我联系。