通过 AWS 开发工具包创建签名的 S3 和 Cloudfront URL [英] Creating signed S3 and Cloudfront URLs via the AWS SDK

查看:78
本文介绍了通过 AWS 开发工具包创建签名的 S3 和 Cloudfront URL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Has anyone successfully used the AWS SDK to generate signed URLs to objects in an S3 bucket which also work over CloudFront? I'm using the JavaScript AWS SDK and it's really simple to generate signed URLs via the S3 links. I just created a private bucket and use the following code to generate the 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 进行签名.以前有人做过这样的设置吗?

This works great but I also want to expose a CloudFront URL to my users so they can get the increased download speeds of using the CDN. I setup a CloudFront distribution which modified the bucket policy to allow access. However, after doing this any file could be accessed via the CloudFront URL and Amazon appeared to ignore the signature in my link. After reading some more on this I've seen that people generate a .pem file to get signed URLs working with CloudFront but why is this not necessary for S3? It seems like the getSignedUrl method simply does the signing with the AWS Secret Key and AWS Access Key. Has anyone gotten a setup like this working before?

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

Update: After further research it appears that CloudFront handles URL signatures completely different from S3 [link]. However, I'm still unclear as to how to create a signed CloudFront URL using Javascript.

推荐答案

更新:我将签名功能从下面的示例代码移到了 aws-cloudfront-sign 包.这样你就可以只需要这个包并调用 getSignedUrl().

Update: I moved the signing functionality from the example code below into the aws-cloudfront-sign package on NPM. That way you can just require this package and call getSignedUrl().

经过一些进一步的调查,我找到了一个解决方案,它是 这个答案 以及我在 博托图书馆.S3 URL 签名的处理方式确实与 CloudFront URL 签名不同.如果您只需要签署一个 S3 链接,那么我最初问题中的示例代码对您来说就足够了.但是,如果您想生成使用 CloudFront 分配的签名 URL,则情况会变得稍微复杂一些.这是因为 AWS 开发工具包当前不支持 CloudFront URL 签名,因此您必须自己创建签名.如果您还需要这样做,这里是基本步骤.我假设您已经设置了 S3 存储桶:

After some further investigation I found a solution which is sort of a combo between this answer and a method I found in the Boto library. It is true that S3 URL signatures are handled differently than CloudFront URL signatures. If you just need to sign an S3 link then the example code in my initial question will work just fine for you. However, it gets a little more complicated if you want to generate signed URLs which utilize your CloudFront distribution. This is because CloudFront URL signatures are not currently supported in the AWS SDK so you have to create the signature on your own. In case you also need to do this, here are basic steps. I'll assume you already have an S3 bucket setup:

  1. 创建 CloudFront 分配
  2. 使用以下设置配置您的来源
    • 源域名:{your-s3-bucket}
    • 限制存储桶访问:是
    • 授予对存储桶的读取权限:是的,更新存储桶政策

创建签名的 CloudFront URL

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

Create Signed CloudFront URL

To great a signed CloudFront URL you just need to sign your policy using RSA-SHA1 and include it as a query param. You can find more on custom policies here but I've included a basic one in the sample code below that should get you up and running. The sample code is for Node.js but the process could be applied to any language.

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

这篇关于通过 AWS 开发工具包创建签名的 S3 和 Cloudfront URL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆