是否有人成功使用AWS开发工具包为S3存储桶中的对象生成签名URL,该URL也可以在CloudFront上运行?我使用的是JavaScriptAWS开发工具包,通过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访问任何文件,Amazon似乎忽略了我链接中的签名。阅读更多内容后,我发现人们会生成一个.pem文件来获取与CloudFront一起使用的已签名URL,但是为什么S3不需要这样做呢?似乎getSignedUrl方法只是使用AWS密钥和AWS访问密钥进行签名。有人有没有像这样工作过的设置?
更新: 经过进一步研究,CloudFront处理的URL签名似乎与S3link完全不同。但是,对于如何使用Javascript创建签名的CloudFront URL,我仍然不清楚。
更新: 我将签名功能从下面的示例代码移到了NPM上的aws-cloudfront- sign软件包中。这样,您只需要此程序包并致电即可getSignedUrl()。
getSignedUrl()
经过进一步的研究,我找到了一种解决方案,该解决方案是此答案与我在Boto库中找到的方法之间的组合。确实,S3URL签名与CloudFrontURL签名的处理方式不同。如果您只需要签名S3链接,那么我最初的问题中的示例代码将对您很好。但是,如果您要生成利用CloudFront发行版的签名URL,它将变得更加复杂。这是因为AWSSDK当前不支持CloudFrontURL签名,因此您必须自己创建签名。如果您还需要执行此操作,请执行以下基本步骤。我假设您已经有一个S3存储桶设置:
要获得一个经过签名的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