首页 文章

使用授权签名Ver 4从浏览器直接上传到S3

提问于
浏览
0

我需要直接从浏览器上传文件到S3 . 一开始我创建了一个正在运行的脚本但是要授权我需要将我的凭据放入accessKeyId和secretAccessKey,这是不安全的 .

我发现我可以用于授权“Authorization Signature

它看起来很棒,但我无法找到我可以将此授权标头放在upload() method中的请求的位置 .

我的授权 Headers 的一个示例:

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

谢谢你的建议 .

2 回答

  • 0

    我找到了解决这个问题的方法 . 我的解决方案基于此site的示例 .

    在最终解决方案中,我不使用javascript SDK,它使用带有授权输入的帖子表单,使用post参数发送的内容 .

  • 1

    您可以使用您的POST请求附上已签名的policy document,以便使用AWS签名版本4进行安全身份验证 .

    如果您在Node上,则可以使用服务器上的aws-s3-form软件包生成客户端所需的表单数据,以便向S3发送成功的请求 .

    您可能想要阅读关于该主题的blog post以获得完整的洞察力 .

    示例服务器端代码(节点)

    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,
          })
        },
      },
    })
    

    示例客户端代码

    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`)
          })
      }
    }
    

相关问题