August
19th,
2009
本文涉及到的所有内容都是以utf-8编码的。 1. 表单内容
上传地址的s3-bucket.s3.amazonaws.com中s3-bucket为使用者所拥有的bucket。上述表单使用了一些常用的字段:
- key 上传的文件名;
- AWSAccessKeyId 从Amazon获得的access key;
- acl 访问控制,可以设置为:private(私有), public-read(公开), public-read-write, authenticated-read.
- success_action_redirect 上传成功后浏览器被重定向到这个地址,并且附带上bucke/key/etag三个参数和文件的hash值;
- policy 表单鉴权策略,base64编码的格式字符串;下面单独介绍;
- signature policy和AWS Secret Key的签名结果,用于保证上传是合法的;
- content-type 文件mime类型,默认为 application/octet-stream , 应填写该值便于浏览器识别文件类型;
- file 上传的文件。 policy policy用于保证该表单是由合法的S3用户所创建的;policy为JSON格式的字符串:
{"expiration": "2009-01-01T00:00:00Z",
"conditions": [
{"bucket": "s3-bucket"},
["starts-with", "$key", "uploads/"],
{"acl": "private"},
{"success_action_redirect": "http://localhost/"},
["starts-with", "$Content-Type", ""],
["content-length-range", 0, 1048576]
]
}
expiration: 表示policy的有效时间; conditions: policy规则,应包含表单中所有的字段,所以这里列出了acl, success_action_redirect, 和 Content-Type;同时policy包含了content-length-range,用于限制上传的文件大小;
policy有3中类型的规则:
- Equality: 表单中的字段值设置为相应的字符串,例如:{“acl”: “private”}
- Starts-With:检查表单字段值是否以给定的字符串开始,为一个三元组,例如:[“starts-with”, “$key”, “uploads/”], $key为表单字段名,表单字段的值必须是“upload/”开头的;
- Content length:三元组,表示文件长度的最小、最大值。
2. 签名
- 首先将policy用base64编码,将其放到表单的policy字段中;
- 用AWS secret key作为密码将policy签名,算法为SHA-1 HMAC; 签名后的结果再用base64编码; 示例代码:
Ruby
require 'base64'
require 'openssl'
require 'digest/sha1'
policy = Base64.encode64(policy_document).gsub("\n","")
signature = Base64.encode64(
OpenSSL::HMAC.digest(
OpenSSL::Digest::Digest.new('sha1'),
aws_secret_key, policy)
).gsub("\n","")
Java
import sun.misc.BASE64Encoder;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
String policy = (new BASE64Encoder()).encode(
policy_document.getBytes("UTF-8")).replaceAll("\n","").replaceAll("\r","");
Mac hmac = Mac.getInstance("HmacSHA1");
hmac.init(new SecretKeySpec(
aws_secret_key.getBytes("UTF-8"), "HmacSHA1"));
String signature = (new BASE64Encoder()).encode(
hmac.doFinal(policy.getBytes("UTF-8")))
.replaceAll("\n", "");
Python
import base64
import hmac, sha
policy = base64.b64encode(policy_document)
signature = base64.b64encode(
hmac.new(aws_secret_key, policy, sha).digest())
本文为翻译缩略版,原文出处:http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1434&categoryID=55 更多详细内容,请参考手册:http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?UsingHTTPPOST.html