Skip to main content
 首页 » 编程设计

python之使用 Python 生成 Amazon S3 CORS 签名

2025年05月04日9三少

让 S3 接受通过 PhoneGap (Cordova) FileTransfer.upload() 生成的 CORS POST 请求的上传真是太糟糕了。对于我可能遗漏的任何建议,我们将不胜感激。目前我使用下面的代码收到 403 AccessDenied 响应。对照S3的文档翻了很多遍,都找不到问题。

这是生成签名的 Python 代码:

# 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() 
) 

此过程生成的签名与 S3 Signature Tester 生成的签名匹配(将 base64 策略转换为十六进制,然后使用 key 通过签名测试器运行)。

将生成的策略和签名传递给客户端,并使用此 PhoneGap FileTransfer 调用构建对 S3 的请求:

// 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); 

这是 CORS 配置(是的,我打算在上传工作后将其锁定):

<?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> 

这是存储桶策略:

{ 
    "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>" 
        } 
    ] 
} 

更新:

这是 Python 将对象转换为 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" 
} 

请您参考如下方法:

您是否尝试删除政策中的换行符?

这是政策的 Ruby 代码,由 s3_file_upload 提供:

Base64.encode64(policy_data.to_json).gsub("\n", "") 

请让我知道您是否成功上传,因为我正在尝试做同样的事情。