问题
I'm trying to set the storage class of an uploaded image to an AWS S3 bucket. I have it working except for adding the storage class to the request. The S3 Post Object Documentation states there can be a form input field named "x-amz-storage-class" but adding it, or any other field, throws an AWS error indicating that there are too many input fields for the post. I tried adding it to the object policy but that causes an Policy error: "Policy Condition failed: [“eq”, “$x-amz-storage-class”, “ONEZONE_IA”]". I'm using JSP and the form's input fields are shown below. Any help would be appreciated.
<input type="hidden" name="key" value="<%= imageFileName %>">
<input type="hidden" name="AWSAccessKeyId" value="<%= S3AccessKeyId %>">
<input type="hidden" name="acl" value="private">
<input type="hidden" name="success_action_redirect" value="<%= s3SuccessAction %>">
<input type="hidden" name="policy" value="<%= encPolicy %>" >
<input type="hidden" name="signature" value="<%= signature %>" >
<input type="hidden" name="Content-Type" value="image/jpeg">
<input type="hidden" name="x-amz-storage-class" value="ONEZONE_IA"> ***** CAUSES ERROR ****
Errors:
Invalid according to Policy: Policy Condition failed: [“eq”, “$x-amz-storage-class”, “STANDARD_IA”]
<Error>
<Code>AccessDenied</Code>
<Message>
Invalid according to Policy: Extra input fields: x-amz-storage-class
</Message>
<RequestId>1104FC046523752C</RequestId>
<HostId>
m0xPpMKJqBG6kZsdQfl/RY92dHprnvtGtrijHLqVtieM51ew+Mkp0mXGbTwKM7OsoUq6ZZUVIc0=
</HostId>
</Error>
回答1:
I have this working now. The policy has fields that must match the fields on the form. "x-amz-storage-class" has to be added to both the form fields and policy. My guess is the encoded policy is signed for security reasons which makes it secure and the form fields must match the policy fields to ensure they weren't changed. Why both are needed is beyond me. Corrected code is below:
<fieldset>
<input type="hidden" name="key" value="<%= imageFileName %>">
<input type="hidden" name="AWSAccessKeyId" value="<%= S3AccessKeyId %>">
<input type="hidden" name="acl" value="private">
<input type="hidden" name="success_action_redirect" value="<%= s3SuccessAction %>">
<input type="hidden" name="policy" value="<%= encPolicy %>" >
<input type="hidden" name="signature" value="<%= signature %>" >
<input type="hidden" name="Content-Type" value="image/jpeg">
<input type="hidden" name="x-amz-storage-class" value="ONEZONE_IA">
public static String encodeS3Policy(String s3SuccessAction, String bucket) throws Exception
{
String policy =
"{\"expiration\": \"2040-01-01T00:00:00Z\"," +
"\"conditions\": [" +
"{\"bucket\": \"" + bucket + "\"}," +
"[\"starts-with\", \"$key\", \"\"]," +
"{\"acl\": \"private\"}," +
"{\"success_action_redirect\": \"" + s3SuccessAction + "\"}," +
"[\"starts-with\", \"$Content-Type\", \"\"]," +
"{\"x-amz-storage-class\": \"ONEZONE_IA\"}," +
"[\"content-length-range\", 0, 10485760]" + // 10 MB max file up load
"]" +
"}";
policy.replaceAll("\n","").replaceAll("\r","");
// Encode the policy
String encPolicy = Base64.getEncoder().encodeToString(policy.getBytes("UTF-8"));
return encPolicy;
}
For completeness and because its not obvious, the storage class values are:
Default: STANDARD
STANDARD | REDUCED_REDUNDANCY | GLACIER | STANDARD_IA | ONEZONE_IA | INTELLIGENT_TIERING | DEEP_ARCHIVE
Here is the AWS S3 Post Object documentation
来源:https://stackoverflow.com/questions/64975612/aws-s3-post-object-rejects-extra-form-fields