admin管理员组

文章数量:1326104

I am trying to get hold of my image objects from S3, from my JavaScript frontend application.

Acording to the documentation, these are the steps required:

import * as AWS from "aws-sdk";

AWS.config.update({accesKeyId, secretAccesKey, region});

let s3 = new AWS.S3();

And then, you can get the objects like so:

function listObjects(bucketName, folderName) {
  return new Promise((resolve) => {
    s3.listObjects({Bucket: bucketName, Prefix: folderName}).promise()
      .then((data) => {
        resolve(data.Contents);
      })
  });
}

All seems to work correctly, but what worries me is that I also need to keep the accessKeyId and the secretAccessKey in my frontend application, in order to access the bucket.

How does one secure the bucket, or access the objects without providing these confidential data?

I am trying to get hold of my image objects from S3, from my JavaScript frontend application.

Acording to the documentation, these are the steps required:

import * as AWS from "aws-sdk";

AWS.config.update({accesKeyId, secretAccesKey, region});

let s3 = new AWS.S3();

And then, you can get the objects like so:

function listObjects(bucketName, folderName) {
  return new Promise((resolve) => {
    s3.listObjects({Bucket: bucketName, Prefix: folderName}).promise()
      .then((data) => {
        resolve(data.Contents);
      })
  });
}

All seems to work correctly, but what worries me is that I also need to keep the accessKeyId and the secretAccessKey in my frontend application, in order to access the bucket.

How does one secure the bucket, or access the objects without providing these confidential data?

Share Improve this question asked Dec 11, 2018 at 16:47 Wilhelm SorbanWilhelm Sorban 1,1311 gold badge19 silver badges38 bronze badges 1
  • it is a very bad idea to expose your credentials in front end. You may just want to make that image public as oppose to making your credentials public. – Asdfg Commented Dec 11, 2018 at 17:27
Add a ment  | 

3 Answers 3

Reset to default 10

You're right to worry. Any one will be able to take the credentials out of your app. There's a few approaches to this:

  • if the objects aren't actually sensitive, then there's nothing lost if the credential can only take the actions you wish to allow everyone. For that matter you should be able to get rid of the need for credentials all together if you set the permissions on your bucket properly .. I think that includes list permissions if necessary.

  • if the objects are sensitive, then you already have some sort of authentication system for your users. IF you're using Oauth accounts to auth ( google, amazon, facebook ,etc ) then you can use AWS Cognito to generate short lived AWS credentials that are associated to that user, which would allow you to differentiate permissions between users ... it's pretty slick and a great fit if already using oauth. IF you're not using oauth, consider whether you should be. It's far more secure than having to hande your own auth creds layer for your users. https://aws.amazon./cognito/

  • if you don't want to or can't user cognito, you can still assume an AWS role from the backend and generate temporary credentials that automatically expire in anywhere from 15 minutes to 1 hour or more and then pass those credentials to the front end. I'd call it "poor man's cognito" but I think it's probably actually more expensive to run the infra to provide the service than cognito costs.

  • Or, as @Tomasz Swinder suggests, you can simply proxy the requests through your application, resolving the asset the user requests to an s3 resource and pulling it in your backend and then serving to your user. This is an inferior solution in most cases because your servers are farther away from the end user than s3's endpoints are likely to be. And, you have to run infrastructure to proxy. But, that having been said, it has it's place.

  • Finally, pre-signed s3 urls may be a good fit for your application. Typically a backend would sign the s3 urls directly before providing them to the user. The signature is enough to authorize the operation ( which can be PUT or GET) but doesn't itself contain the private key used to sign - in other words, presigned urls provide an authorized URL but not the credentials used to authorize them, so they're a great way to provide ad hoc authorization to s3.

Overall it's really awesome to have a backend-free application, and for that you're going to need a 3rd party auth and something like cognito. but once you start using it, you can then use all sorts of aws services to provide what would otherwise be done by a backend. Just be careful with permissions because aws is all pay as you go and there's usually no capability to limit the calls to a service to make sure a cruel internet user strives to drive up your AWS bill by making tons of calls with the temporary creds you've provided them. One notable exception to that is API Gateway, which does allow per user rate limits and therefore is a great fit for a cognito-authorized serverless backend.

Also bear in mind that LISTing s3 objects is both much slower, and much more expensive ( still cheap per op, but 10x ) than GETing s3 objects, so it's usually best to avoid calling lIST whenever possible. I'm just throwing that out there, I suspect you're just doing that to test out the s3 connection.

Could you request that through your server? or is it a static site?

If this is a static site then, You can create IAM User for s3 that can only read the content that you are going to use and show in the fronted anyway.

One method we use is to store the credentials in a .env file and use dotenv (https://github./motdotla/dotenv) to read in the variables. These can then be accessed through process.env. For example, the .env file would contain:

AWSKEY=1234567abcdefg
AWSSECRET=hijklmn7654321
REGION=eu-west

Then in your code you would then call require('dotenv').load() to read the environment variables. You then access them as:

AWS.config.update({process.env.AWSKEY, process.env.AWSSECRET, process.env.REGION});

Make sure that the .env file is not mitted into your repo. If you want you could have a env.example and instructions on how to create a .env when creating either a dev or production install.

As for securing the bucket, you can do so by restricting the read/write access to an IAM user that owns the AWS key/secret pair.

本文标签: javascriptStoring AWS credentials in the frontendStack Overflow