Direct Upload to S3 from the browser with Authorization Signature Ver 4

I need to upload a file to S3 directly from the browser. In the beginning I created a script that is working but to authorize I need to put my credentials accessKeyId and secretAccessKey, what it is not secure.

I figured out that I can use for authorization the "Authorization Signature"

It seems great but I can't find where I can put this authorization header to the request in the upload() method.

An example of my authorization header:

Authorization: AWS4-HMAC-SHA256 Credential=/20151016//s3/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=4eee344a71a58623febc4079024a27cb62f3d26546695422244fcefe50d0168d

Thanks for your advice.


I have found solution for this issue. My solution is based on example from this site.

In final solution I don't use javascript SDK, it is using post form with authorization inputs what is sending with post parameters.


You can enclose a signed policy document with your POST request in order to authenticate securely, with AWS Signature Version 4.

If you're on Node, you can use the aws-s3-form package on the server to generate the necessary form data your client requires in order to send a successful request to S3.

You might want to read my blog post on the subject for full insight.

Example Server Side Code (Node)

let AwsS3Form = require('aws-s3-form')

[...]

// A hapi.js server route
server.route({
  method: ['GET',],
  path: '/api/s3Settings',
  config: {
    auth: 'session',
    handler: (request, reply) => {
      let {key,} = request.query

      let keyPrefix = `u/${request.auth.credentials.username}/`
      let region = process.env.S3_REGION
      let s3Form = new AwsS3Form({
        accessKeyId: process.env.AWS_ACCESS_KEY,
        secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
        region,
        bucket,
        keyPrefix,
        successActionStatus: 200,
      })
      let url = `https://s3.${region}.amazonaws.com/${bucket}/${keyPrefix}${key}`
      let formData = s3Form.create(key)
      reply({
        bucket,
        region,
        url,
        fields: formData.fields,
      })
    },
  },
})

Example Client Side Code

let R = require('ramda')

let ajax = require('./ajax')

class S3Uploader {
  constructor({folder,}) {
    this.folder = folder
  }

  send(file) {
    let key = `${this.folder}/${file.name}`
    return ajax.getJson(`s3Settings`, {key,})
      .then((s3Settings) => {
        let formData = new FormData()
        R.forEach(([key, value,]) => {
          formData.append(key, value)
        }, R.toPairs(s3Settings.fields))
        formData.append('file', file)

        return new Promise((resolve, reject) => {
          let request = new XMLHttpRequest()
          request.onreadystatechange = () => {
            if (request.readyState === XMLHttpRequest.DONE) {
              if (request.status === 200) {
                resolve(s3Settings.url)
              } else {
                reject(request.responseText)
              }
            }
          }

          let url = `https://s3.${s3Settings.region}.amazonaws.com/${s3Settings.bucket}`
          request.open('POST', url, true)
          request.send(formData)
        })
      }, (error) => {
        throw new Error(`Failed to receive S3 settings from server`)
      })
  }
}
链接地址: http://www.djcxy.com/p/39036.html

上一篇: AWS签名v4验证成功执行EU存储桶,但美国存储桶失败?

下一篇: 使用Authorization Signature Ver 4从浏览器直接上传到S3