通过AWS SDK创建签名的S3和Cloudfront URL

 way旧光影 发布于 2023-01-29 18:06

是否有人成功使用AWS SDK生成S3存储桶中对象的签名URL,这些URL也可以在CloudFront上运行?我正在使用JavaScript AWS SDK,通过S3链接生成签名URL非常简单.我刚刚创建了一个私有存储桶并使用以下代码生成URL:

var AWS = require('aws-sdk')
  , s3 = new AWS.S3()
  , params = {Bucket: 'my-bucket', Key: 'path/to/key', Expiration: 20}

s3.getSignedUrl('getObject', params, function (err, url) {
  console.log('Signed URL: ' + url)
})

这很好但我也希望向用户公开CloudFront URL,以便他们可以获得使用CDN的更高下载速度.我设置了一个CloudFront发行版,它修改了存储桶策略以允许访问.但是,执行此操作后,任何文件都可以通过CloudFront URL访问,而亚马逊似乎忽略了我的链接中的签名.在阅读了更多内容后,我发现有人生成一个.pem文件来获取使用CloudFront的签名URL,但为什么S3不需要这样做?似乎getSignedUrl方法只使用AWS Secret Key和AWS Access Key进行签名.有没有人得到过这样的设置呢?

更新: 经过进一步研究后,CloudFront似乎处理的URL签名完全不同于S3 [link].但是,我仍然不清楚如何使用Javascript创建签名的CloudFront URL.

1 个回答
  • 更新:我将签名功能从下面的示例代码移动到NPM上的aws-cloudfront-sign包中.这样你只需要这个包并打电话getSignedUrl().


    经过一些进一步的调查后,我找到了一个解决方案,它是这个答案与我在Boto库中找到的方法之间的一种组合.确实,S3 URL签名的处理方式与CloudFront URL签名不同.如果您只需要签署一个S3链接,那么我的初始问题中的示例代码将适用于您.但是,如果要生成使用CloudFront分配的签名URL,则会更复杂一些.这是因为AWS SDK当前不支持CloudFront URL签名,因此您必须自己创建签名.如果您还需要这样做,这里是基本步骤.我假设您已经安装了S3存储桶:

    配置CloudFront

      创建CloudFront分配

      使用以下设置配置原点

      来源域名:{your-s3-bucket}

      限制存储桶访问:是

      授予Bucket读取权限:是,更新存储桶策略

      创建CloudFront密钥对.应该可以在这里做到这一点.

    创建签名的CloudFront URL

    要想使用签名的CloudFront URL,您只需使用RSA-SHA1签署策略并将其作为查询参数包含在内.您可以在此处找到有关自定义策略的更多信息,但我在下面的示例代码中包含了一个基本的策略,可以让您启动并运行.示例代码适用于Node.js,但该过程可以应用于任何语言.

    var crypto = require('crypto')
      , fs = require('fs')
      , util = require('util')
      , moment = require('moment')
      , urlParse = require('url')
      , cloudfrontAccessKey = '<your-cloudfront-public-key>'
      , expiration = moment().add('seconds', 30)  // epoch-expiration-time
    
    // Define your policy.
    var policy = {
       'Statement': [{
          'Resource': 'http://<your-cloudfront-domain-name>/path/to/object',
          'Condition': {
             'DateLessThan': {'AWS:EpochTime': '<epoch-expiration-time>'},
          }
       }]
    }
    
    // Now that you have your policy defined you can sign it like this:
    var sign = crypto.createSign('RSA-SHA1')
      , pem = fs.readFileSync('<path-to-cloudfront-private-key>') 
      , key = pem.toString('ascii')
    
    sign.update(JSON.stringify(policy))
    var signature = sign.sign(key, 'base64')
    
    // Finally, you build the URL with all of the required query params:
    var url = {
      host: '<your-cloudfront-domain-name>',
      protocol: 'http',
      pathname: '<path-to-s3-object>'
    }    
    var params = {
      'Key-Pair-Id=' + cloudfrontAccessKey,
      'Expires=' + expiration,
      'Signature=' + signature
    }
    var signedUrl = util.format('%s?%s', urlParse.format(url), params.join('&'))
    
    return signedUrl
    

    2023-01-29 18:09 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有