jef*_*ind 3 python authentication aws-lambda aws-api-gateway
一点背景信息,
我建立了一个交互式网站,用户可以在其中将图像上传到S3。我构建了它,以便使用签名的请求(python django backend)将图像从浏览器直接上传到AWS S3。
现在的问题是,用户希望能够旋转图像。同样,我希望进行此设置,以便用户的请求直接来自浏览器。我构建了一个AWS Lambda函数并将其附加到一个Web api,它将接受POST请求。我一直在测试,终于使它工作了。该函数采用2个输入,key以及rotate_direction,它们作为POST变量到web API通过。它们进入event变量中的python函数。这是简单的Lambda函数:
from __future__ import print_function
import boto3
import os
import sys
import uuid
from PIL import Image
s3_client = boto3.client('s3')
def rotate_image(image_path, upload_path, rotate_direction):
with Image.open(image_path) as image:
if rotate_direction == "right":
image.rotate(-90).save(upload_path)
else:
image.rotate(90).save(upload_path)
def handler(event, context):
bucket = 'the-s3-bucket-name'
key = event['key']
rotate_direction = event['rotate_direction']
download_path = '/tmp/{}{}'.format(uuid.uuid4(), key)
upload_path = '/tmp/rotated_small-{}'.format(key)
s3_client.download_file(bucket, key, download_path)
rotate_image(download_path, upload_path, rotate_direction)
s3_client.delete_object(Bucket=bucket, Key=key)
s3_client.upload_file(upload_path, bucket, key)
return { 'message':'rotated' }
Run Code Online (Sandbox Code Playgroud)
一切正常。所以现在我的问题是如何对该系统实施某种身份验证?有关每个图像的所有权详细信息位于django Web服务器上。虽然所有图像都被认为是“公开的”,但我希望强制每个图像的所有者只能旋转其自己的图像。
通过这个项目,我一直在通过直接从浏览器发出内容请求进入新的领域。我可以理解如何仅通过从Web服务器发出POST请求来控制访问,在Web服务器中可以验证图像的所有权。请求是否仍可能来自浏览器?
小智 5
TL; DR解决方案:创建一个Cognito身份池,分配策略的用户只能上传以其Identity ID为前缀的文件。
如果我正确理解了您的问题,则想为存储在S3上的图像设置一种公开可见的方式,但只能由上传它的用户编辑。实际上,您无需浏览Lambda函数就可以在浏览器中验证文件所有权,旋转图像并将旋转的图像上传到S3。
步骤1:创建Cognito用户池以创建用户目录。如果您已经具有用户登录/注册身份验证系统,则可以跳过此步骤。
步骤2:创建一个Cognito身份池以启用联盟身份,以便您的用户可以从身份池中获得临时AWS凭证,并使用它将文件上传到S3,而无需通过服务器/ lambda。
第3步:在创建Cognito身份游泳池,您可以定义什么S3资源的用户被允许访问的策略。这是一个示例政策
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"mobileanalytics:PutEvents",
"cognito-sync:*",
"cognito-identity:*"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::YOUR_S3_UPLOADS_BUCKET_NAME/*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::YOUR_S3_UPLOADS_BUCKET_NAME/${cognito-identity.amazonaws.com:sub}*"
]
}
]
}
Run Code Online (Sandbox Code Playgroud)
请注意,第二个块将“ S3:GetObject”分配给S3存储桶中的所有文件;和第三块受让人“S3:PutObject”到文件只有前缀与用户的Cognito标识ID。
步骤4:在前端JS中,从Cognito身份池获取临时证书
export function getAwsCredentials(userToken) {
const authenticator = `cognito-idp.${config.cognito.REGION}.amazonaws.com/${config.cognito.USER_POOL_ID}`;
AWS.config.update({ region: config.cognito.REGION });
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: config.cognito.IDENTITY_POOL_ID,
Logins: {
[authenticator]: userToken
}
});
return new Promise((resolve, reject) => (
AWS.config.credentials.get((err) => {
if (err) {
reject(err);
return;
}
resolve();
})
));
}
Run Code Online (Sandbox Code Playgroud)
步骤5:使用凭据将文件上传到S3,并在文件名前添加用户的Cognito身份ID。
export async function s3Upload(file, userToken) {
await getAwsCredentials(userToken);
const s3 = new AWS.S3({
params: {
Bucket: config.s3.BUCKET,
}
});
const filename = `${AWS.config.credentials.identityId}-${Date.now()}-${file.name}`;
return new Promise((resolve, reject) => (
s3.putObject({
Key: filename,
Body: file,
ContentType: file.type,
ACL: 'public-read',
},
(error, result) => {
if (error) {
reject(error);
return;
}
resolve(`${config.s3.DOMAIN}/${config.s3.BUCKET}/${filename}`);
})
));
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
882 次 |
| 最近记录: |