[英]How to authenticate serverless web request using AWS Web API and Lambda?
Little background info, 小背景信息,
I have built an interactive website where users can upload images to S3. 我建立了一个互动网站,用户可以将图像上传到S3。 I built it so the image upload goes right from the browser to AWS S3 using a signed request ( python django backend ).
我构建了它,因此使用签名请求(python django后端)将图像上传从浏览器直接传送到AWS S3。
Now the issue is, the users wish to be able to rotate the image. 现在的问题是,用户希望能够旋转图像。 I Similarly I would like this set up so the user's request goes straight from the browser.
我同样我希望这样设置,以便用户的请求直接来自浏览器。 I built an AWS Lambda function and attached it to a web api, which will accept POST requests.
我构建了一个AWS Lambda函数并将其附加到web api,它将接受POST请求。 I have been testing and I finally got it working.
我一直在测试,我终于开始工作了。 The function takes 2 inputs,
key
, and rotate_direction
, which are passed as POST variables to the web api. 该函数接受2个输入,
key
和rotate_direction
,它们作为POST变量传递给web api。 They come into the python function in the event
variable. 它们进入
event
变量的python函数。 Here is the simple Lambda function: 这是简单的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' }
Everything is working. 一切正常。 So now my issue is how to enforce some kind of authentication for this system?
那么现在我的问题是如何为这个系统强制执行某种身份验证? The ownership details about each image reside on the django web server.
每个映像的所有权详细信息都驻留在django Web服务器上。 While all the images are considered "public", I wish to enforce that only the owner of each image is allowed to rotate their own images.
虽然所有图像都被视为“公开”,但我希望强制只允许每个图像的所有者旋转自己的图像。
With this project I have been venturing into new territory by making content requests right from the browser. 通过这个项目,我一直在通过浏览器发出内容请求进入新的领域。 I could understand how I could control access by only making the POST requests from the web server, where I could validate the ownership of the images.
我可以理解如何通过仅从Web服务器发出POST请求来控制访问,在那里我可以验证图像的所有权。 Would it still be possible having the request come from the browser?
是否仍然可以通过浏览器提出请求?
TL;DR Solution: create a Cognito Identity Pool, assign policy users can only upload files prefixed by their Identity ID. TL; DR解决方案:创建一个Cognito Identity Pool,分配策略用户只能上传以其身份ID为前缀的文件。
If I understand your question correctly, you want to setup a way for an image stored on S3 to be viewable by public , yet only editable by the user who uploaded it . 如果我正确理解您的问题,您希望为存储在S3上的图像设置一种方式,供公众查看 ,但只能由上传它的用户编辑 。 Actually, you can verify file ownership, rotate the image and upload the rotated image to S3 all in the browser without going through a Lambda function.
实际上,您可以在浏览器中验证文件所有权,旋转图像并将旋转的图像上传到S3,而无需通过Lambda函数。
Step 1: Create a Cognito User Pool to create a user directory. 步骤1:创建Cognito用户池以创建用户目录。 If you already have a user login/sign up authentication system, you could skip this step.
如果您已拥有用户登录/注册身份验证系统,则可以跳过此步骤。
Step 2: Create a Cognito Identify Pool to enable federated identity, so your users can get a temporary AWS credential from the Identity Pool, and use it to upload files to S3 without going through your server/lambda. 步骤2:创建Cognito Identify Pool以启用联合身份,以便您的用户可以从Identity Pool获取临时AWS凭证,并使用它将文件上载到S3而无需通过您的server / lambda。
Step 3: When creating the Cognito Identity Pool, you can define a policy on what S3 resources a user is allowed to access. 步骤3:创建Cognito Identity Pool时,您可以定义允许用户访问哪些S3资源的策略。 Here is a sample policy
这是一个示例政策
{
"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}*"
]
}
]
}
Note the second block assigns "S3:GetObject" to all files in your S3 bucket; 注意第二个块将“S3:GetObject”分配给S3存储桶中的所有文件; and the third block assigns "S3:PutObject" to ONLY FILES prefixed with the user's Cognito Identity ID.
第三个块将“S3:PutObject”分配给以用户的Cognito Identity ID为前缀的ONLY FILES。
Step 4: In frontend JS, get a temporary credential from Cognito Identity Pool 第4步:在前端JS中,从Cognito Identity Pool获取临时凭证
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();
})
));
}
Step 5: Upload files to S3 with the credential, prefix the file name with the user's Cognito Identity ID. 步骤5:使用凭证将文件上载到S3,使用用户的Cognito Identity 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}`);
})
));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.