阅读更多类似的文章,visit my blog
将文件上传到远程服务器是任何现代应用程序中最常见的任务之一。 AWS拥有一个名为S3(简单存储服务)的服务,这使这项工作非常容易。
但是您知道我们如何安全地访问水桶?
好吧,今天我们将看到我们如何安全地执行最常见的2个操作
-
上传文件到S3
-
下载来自S3
的文件
让我们从上传文件开始。
第一件事首先
我假设您已经知道如何创建S3存储桶。如果没有大量文章。
您可以从已经拥有的任何存储桶开始,然后执行以下
转到 bucket - > 权限 - > 阻止所有公共访问
现在,我们的水桶已安全。现在,当任何人试图访问存储桶时,他们会看到它而不是实际文件。
好吧,现在我们已经确保了水桶。但是我们需要正确访问吗?
让我们从如何将文件上传到存储桶开始。
选项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。
然后,我们可以使用axios
或fetch
直接从前端发送对象。
这种方法的好处
-
我们不需要在前端代码中存储任何类型的秘密。
-
我们不需要等待将实际文件发送到后端,从而将响应时间减少了 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与我联系。