大咖专栏 | 使用Amazon CloudFront签名URL+S3实现私有内容发布(Part 2)
大咖专栏
大咖专栏主要刊登亚马逊AWS诸位大咖亲自撰写的Blog,内容涉猎广泛,话题讨论前沿,且与实战紧密相连。我们非常欢迎小伙伴们在评论区留言,与大咖互动交流!
今天为大家撰文的大咖,是亚马逊AWS解决方案架构师——蒙维老师。
蒙维
AWS解决方案架构师亚马逊AWS解决方案架构师,负责基于AWS的云计算方案架构咨询和设计,有超过十年以上电信行业和移动互联网行业复杂应用系统架构和设计经验,主要擅长分布式和高可用软件系统架构设计、移动互联网应用解决方案设计、研发机构DevOps最佳实施过程。
接上篇:
《大咖专栏 | 使用Amazon CloudFront签名URL+S3实现私有内容发布(Part 1)》
更新CloudFront WEB发布点
启用签名URL功能
1. 使用具有完整CloudFront操作权限的IAM用户登录Global AWS Web控制台
2. 访问访问“服务”-->“网络和内容分发”-->“CloudFront”
3. 选中之前创建的Web发布点,执行“Distribution Settings”
4. 选中“Behavior”标签,编辑“Default (*)”。
5. 设置“Restrict Viewer Access (Use Signed URLs or Signed Cookies)”为“Yes”
6. 设置“Trusted Signers”为“Self”
说明:
表示使用当前登录的IAM用户所对应的AWS 账号来签名URL请求,“Trusted Signers”设置需要对应之前在创建的CloudFront密钥对时使用的AWS根账号。
7. 执行“Yes,Edit”按钮提交更新
8. 刚刚更新完成的Web发布点将处于“In Progress”(正在部署)状态。
9. 请耐心等待Web发布点最终变为“Deployed”(完成部署)状态。
开发签名URL生成器
CloudFront支持使用各种开发语言和工具产生签名URL。在这篇博客里,我提供了一个使用JAVA语言开发签名URL生成器的完整例子。整个项目包括源码和依赖的库文件都打包成了完整的Eclipse项目文件,用户只需要下载后执行Eclipse的项目导入操作就可以进行代码研究和测试。
JAVA版的签名URL生成器主要依赖了一个第三方开源项目jets3t的相关库文件。jets3t项目开发了一套完整的JAVA工具来访问Amazon S3、Amazon CloudFront和 Google Storage Service。 关于jets3项目的详情请参考其官网链接。
下面的步骤详细介绍了如何使用jets3t相关工具类来开发CloudFront签名URL生成器:
1. 使用openssl转换下载的PEM格式CloudFront密钥对对应私钥文件成为DER格式
f45c89a82b15:cert weimen$ openssl pkcs8 -topk8 -nocrypt -in pk-APKAJW4W4KMUGDXXXXXX.pem -inform PEM -out cdnPK.der -outform DER
2. 下面的代码片段展示了签名URL生成器的实现细节:
a) 读取DER格式的CloudFront 密钥对的私钥文件
b) 构造被签名URL
c) 构造定制访问权限策略
d) 执行签名
e) 输出签名后的URL
public static void main(String[] args) throws Exception
{
//1.加载Hash和签名算法类
Security.addProvider(
new org.bouncycastle.jce.provider.BouncyCastleProvider());
// ================================================================
// ================2.签名相关参数====================================
// ================================================================
//2.1.CloudFront为发布点分配的域名或者用户自己的域名
String param_DistributionDomain = "自己的域名或cloudfront发布点的域名";
//String param_DistributionDomain = "mw.homyusc.com";
//2.2.转化成"*.der"格式的私钥文件
String param_PrivateKeyFilePath = "本地保存的*.der格式的cloudfront密钥对私钥文件的带路径文件名";
//String param_PrivateKeyFilePath = "/Users/weimen/signedurl/cert/cdnPK.der";
//2.3.S3存储桶中文件的访问Key值
String param_S3ObjectKey = "需要被访问的S3存储桶内文件访问key值";
//String param_S3ObjectKey = "earth.jpg";
//2.4.CloudFront密钥对对应的访问KEY值
String param_KeyPairId = "使用根账号创建的CloudFront密钥对Key值";
//String param_KeyPairId = "APKAJW4W4KMUGDXXXXXX";
//2.5.待签名的URL
//具体协议(http/https)需要和CloudFront发布点设置对应
String param_UrlToBeSigned = "http://或者https://"
+ param_DistributionDomain
+ "/"
+ param_S3ObjectKey;
/*
String param_UrlToBeSigned = "https://"
+ param_DistributionDomain
+ "/"
+ param_S3ObjectKey;
*/
//3.加载私钥文件内容
byte[] derPrivateKey =
ServiceUtils.readInputStreamToBytes(
new FileInputStream(param_PrivateKeyFilePath));
// ================================================================
// ================4.定制策略相关参数================================
// ================================================================
//4.1.权限策略生效的路径,可以使用"*"和"?"来实现批量匹配,
//具体协议(http/https)需要和CloudFront发布点设置对应
String param_PolicyResourcePath = "http://或者https://"
+ param_DistributionDomain
+ "/"
+ param_S3ObjectKey;
/*
String param_PolicyResourcePath = "https://"
+ param_DistributionDomain
+ "/"
+ param_S3ObjectKey;
*/
//4.2.签名URL失效时间
Date param_DateLessThan = ServiceUtils.parseIso8601Date("UTC格式的签名URL失效时间");
//Date param_DateLessThan = ServiceUtils.parseIso8601Date("2017-06-30T22:20:00.000Z");
//4.3.请求客户端的Ip地址范围CIDR设置(可选参数)
String param_limitToIpAddressCIDR = "CIDR格式的请求源IP地址范围";
//String param_limitToIpAddressCIDR = "0.0.0.0/0";
//4.4.签名URL生效时间(可选参数,不输入立即生效)
Date param_DateGreaterThan = ServiceUtils.parseIso8601Date("UTC格式的签名URL生效时间");
//Date param_DateGreaterThan = ServiceUtils.parseIso8601Date("2017-01-01T06:31:56.000Z");
//5.根据输入参数创建定制策略
String policy =
CloudFrontService.buildPolicyForSignedUrl(
param_PolicyResourcePath,
param_DateLessThan,
param_limitToIpAddressCIDR,
param_DateGreaterThan
);
System.out.println("[INFO]实际构造的的定制策略内容是【" + policy + "】");
//6.执行实际签名操作(哈希+签名+Base64编码)
String signedUrl =
CloudFrontService.signUrl(
param_UrlToBeSigned,
param_KeyPairId,
derPrivateKey,
policy
);
System.out.println("[INFO]输出的签名URL内容【" + signedUrl + "】");
}
3. 读者通过研究上面的代码和注释就可以快速理解签名URL产生的大致流程,然后根据实际需要替换代码中的“签名相关参数”和“定制策略相关参数”(蓝色字体部分),就可以快速开发出属于自己的签名URL生成器。如果需要完整的代码例子,请直接下载对应的Eclipse项目文件。
4. 例子代码产生的签名URL内容类似下面的例子:
https://mw.homyusc.com/earth.jpg?Policy=eyJTdGF0ZW1lbnQiOiBbeyJSZXNvdXJjZSI6Imh0dHBzOi8vbXcuaG9teXVzYy5jb20vZWFydGguanBnIiwiQ29uZGl0aW9uIjp7IkRhdGVMZXNzVGhhbiI6eyJBV1M6RXBvY2hUaW1lIjoxNDk4ODYxMjAwfSwiSXBBZGRyZXNzIjp7IkFXUzpTb3VyY2VJcCI6IjAuMC4wLjAvMCJ9LCJEYXRlR3JlYXRlclRoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTQ4MzI1MjMxNn19fV19&Signature=rJq1~uW3HZIVChPs5X5K9DnM2haH8oy488wXDAIJ6X6DBQAtVJAhsoHkPU3zaChCSGt9wG2uyuC-KslzhAw85K1b~EL52fOhuPf0uJOFAb5PUYW8R4BSyflE-snFfzQs8laanuSmmpHNCDhGw3YrqPjFSBxm~03F5t2ElizLF~0nQdheZHLrnTrdPUMgHK6ffnANjnETul3aB4JAzV8N1Wi5YtjjiTApiPQMJ8QrQaPScq9SonQbZdgqYuG5bzAdTxlW2gRwOfsftKSGNVK8uhczlParWZD8wa-A5PWEaUznaBfHz1Arwiu~JnVGQTqhNPaAZs2BO95t4tqaVSrlWw__&Key-Pair-Id=APKAJW4W4KMUGDXXXXXX
验证测试
1. 当获得了经过签名的URL后,用户就可以在自己的浏览器中输入该签名URL,或者将签名URL提供给自己开发的桌面客户端或移动APP来访问S3存储桶中的对应文件。
2. 用户还可以继续测试各种异常场景:
a) 直接使用S3文件的URL访问
b) 通过CloudFront域名而不是用户自有域名访问
c) 使用Http协议而不是Https协议访问
d) 在允许的时间段之外访问
e) 使用允许的源IP地址段之外访问
基于我们之前的设置,这些操作都将返回失败消息。
总 结
这篇博客完整的介绍了如何利用Amazon CloudFront签名URL功能安全地发布存放在S3存储桶中的私有内容。读者通过研究和学习签名URL生成器的源码,演练完整的CloudFront私有内容发布创建步骤,就可以快速掌握Amazon CloudFront签名URL功能的正确配置和使用方法。
例子源码
https://s3.cn-north-1.amazonaws.com.cn/mwpublic/projects/signedurl/SignedURL.zip
参考链接
Amazon CloudFront产品介绍
https://aws.amazon.com/cn/cloudfront/
Amazon S3产品介绍
https://aws.amazon.com/cn/s3/
创建CloudFront Web发布点
http://docs.aws.amazon.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/distribution-web.html
利用CloudFront发布私有内容
http://docs.aws.amazon.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html
在CloudFront中使用Https
http://docs.aws.amazon.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/using-https.html
利用Java语言开发签名URL
http://docs.aws.amazon.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/CFPrivateDistJavaDevelopment.html
利用C#和.Net框架开发签名URL
http://docs.aws.amazon.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/CreateSignatureInCSharp.html
利用PHP开发签名URL
http://docs.aws.amazon.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/CreateURL_PHP.html
上传和管理CloudFront安全证书
http://docs.aws.amazon.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/cnames-and-https-procedures.html
签名URL定制策略
http://docs.aws.amazon.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/private-content-creating-signed-url-custom-policy.html
jets3t官网
http://www.jets3t.org/
点击“阅读原文”
了解更多AWS官方Blog内容