问题
I'm having a hell of a time getting S3 to accept uploads via CORS POST request generated by PhoneGap (Cordova) FileTransfer.upload(). Any suggestions as to what I may be missing would be appreciated. Currently I'm getting a 403 AccessDenied response using the code below. I've been over it many times comparing with S3's documentation, and can't figure out the problem.
Here is the Python code that generates the signature:
# Create policy document for S3.
policy_obj = {"expiration": "2014-01-01T00:00:00Z",
"conditions": [
{"bucket": "<my.bucket.name>"},
["starts-with", "$key", "story_"],
{"acl": "public-read"},
["eq", "$Content-Type", "audio/mp4"],
["content-length-range", str(0), str(2097152)]
]
}
policy = base64.b64encode(json.dumps(policy_obj))
# Create signature for S3
signature = base64.b64encode(
hmac.new(
key=app.config['AWS_SECRET_KEY'],
msg=policy,
digestmod=hashlib.sha1
).digest()
)
The signature generated by this process matches the signature produced by S3 Signature Tester (converting the base64 policy into Hex and then running that through the Signature Tester with the secret key).
The resulting policy & signature are passed to the client, and the request to S3 is built with this PhoneGap FileTransfer call:
// Upload file to Amazon S3
// r is the response object generated by Python
var options = new FileUploadOptions();
options.chunkedMode = false;
options.mimeType="audio/mp4";
options.fileKey='file';
options.fileName='story_' + uniqueKey + '.m4a';
options.params={
"key": "${filename}",
"acl": "public-read",
"AWSAccessKeyId": r.aws_access_key,
"Policy": r.policy,
"Signature": r.signature,
};
var ft = new FileTransfer();
ft.upload(path, "http://<my.bucket.name>.s3.amazonaws.com/", uploadSuccess, uploadFail, options);
This is the CORS configuration (yes, I plan to lock it down once I get the uploads working):
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
This is the bucket policy:
{
"Version": "2008-10-17",
"Id": "Policy1356975063803",
"Statement": [
{
"Sid": "Stmt1357234455973",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::<my.bucket.name>/*"
},
{
"Sid": "Stmt1356975061658",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::293855469575:root"
},
"Action": "s3:*",
"Resource": "arn:aws:s3:::<my.bucket.name>"
}
]
}
UPDATE:
This is what the policy itself looks like after Python has converted the object into JSON:
{
"conditions": [
{
"bucket": "<my.bucket.name>"
},
[
"starts-with",
"$key",
"story_"
],
{
"acl": "public-read"
},
[
"eq",
"$Content-Type",
"audio/mp4"
],
[
"content-length-range",
"0",
"6291456"
]
],
"expiration": "2014-01-01T00:00:00Z"
}
回答1:
Did you try removing newlines in your policy?
Here is the Ruby code for the policy, courtesy of s3_file_upload:
Base64.encode64(policy_data.to_json).gsub("\n", "")
Please let me know if you managed to get your upload to work, as I'm trying to do the same thing.
来源:https://stackoverflow.com/questions/14165921/generating-amazon-s3-cors-signature-with-python