是否有人成功地使用 AWS 开发工具包为 S3 存储桶中的对象生成签名 URL,这些对象也可以在 CloudFront 上运行?我正在使用 JavaScript AWS SDK通过 S3 链接生成签名 URL 非常简单。我刚刚创建了一个私有(private)存储桶并使用以下代码生成 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 key 和 AWS 访问 key 进行签名。以前有人做过这样的设置吗?
更新: 经过进一步研究,CloudFront 处理的 URL 签名似乎与 S3 [link] 完全不同。 .但是,我仍然不清楚如何使用 Javascript 创建签名的 CloudFront URL。
最佳答案
更新:我将签名功能从下面的示例代码移到 aws-cloudfront-sign在 NPM 上打包。这样你就可以只需要这个包并调用 getSignedUrl()
。
经过进一步调查,我找到了一个解决方案,它是 this answer 之间的一种组合。以及我在 Boto library 中找到的方法.确实,S3 URL 签名的处理方式与 CloudFront URL 签名不同。如果您只需要签署 S3 链接,那么我最初问题中的示例代码对您来说就可以了。但是,如果您想生成使用 CloudFront 分配的签名 URL,它会变得有点复杂。这是因为 AWS 开发工具包当前不支持 CloudFront URL 签名,因此您必须自己创建签名。如果您还需要这样做,这里是基本步骤。我假设您已经设置了 S3 存储桶:
配置 CloudFront
- 创建 CloudFront 分配
- 使用以下设置配置您的来源
- 源域名:{your-s3-bucket}
- 限制存储桶访问:是
- 授予对存储桶的读取权限:是,更新存储桶政策
- 创建 CloudFront key 对。应该可以做到here .
创建签名的 CloudFront URL
要获得出色的签名 CloudFront URL,您只需使用 RSA-SHA1 对策略进行签名并将其作为查询参数包含在内。您可以找到更多关于自定义政策 here但是我在下面的示例代码中包含了一个基本代码,它应该可以帮助您启动并运行。示例代码适用于 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
关于javascript - 通过 AWS 开发工具包创建签名的 S3 和 Cloudfront URL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21521302/