首页 > 解决方案 > AWS S3 Post InvalidPolicydocument 错误:无效的简单条件

问题描述

我正在尝试直接发布到我的 S3 存储桶,并且今天一整天都收到此 400 错误。

<Error>
    <Code>InvalidPolicyDocument</Code>
    <Message>Invalid Policy: Invalid Simple-Condition: Simple-Conditions must have exactly one property specified.</Message>
    <RequestId>6M9N0SAH7K6W9GCJ</RequestId>
    <HostId>6naRbfGG7xVW3hgMSkdnGU6byAtFgEStBL57MdxquKefVNUr/MDP1JWleiQtvPmcgQIilJXnRjc=</HostId>
</Error>

根据文档和我所做的所有搜索,这似乎是政策不匹配的问题?

这是创建Formdata对象的前端 Javascript 代码fd:(httpResponseData 是来自我的服务器的响应,包括所有编码的策略和签名等。)

let fd = new FormData();

fd.append("bucket", httpResponseData.bucket)
fd.append("acl", httpResponseData.bucketAcl);
fd.append("key", file.name);
fd.append("Content-Type", file.type);
fd.append("policy", httpResponseData.encodedPolicy);
fd.append("x-amz-algorithm", "AWS4-HMAC-SHA256");
fd.append("x-amz-credential", httpResponseData.amzCred);
fd.append("x-amz-date", httpResponseData.expirationStrClean);
fd.append("x-amz-meta-type", "post-image");

fd.append("x-amz-signature", httpResponseData.sign);
fd.append("file", file);

这是我在后端定义的政策条件:

const s3Policy = {
    expiration: this.expirationStr,
    conditions: [
        { bucket: this.bucket },
        ["starts-with", "$key", ""], // allows any file name
        { acl: this.bucketAcl },
        ["starts-with", "$Content-Type", "image/"],
        { "x-amz-algorithm": "AWS4-HMAC-SHA256" },
        { "x-amz-credential": this.amzCred },
        { "x-amz-date": this.expirationStrClean },
        { "x-amz-meta-type": "post-image" }
    ],
};

this指的是被实例化的特定对象(显然)。我正在执行这样的签名策略对象的制作:

const crypto = require("crypto");

const AccessKeyId = "My Access Key ID";
const SecretAccessKey = "My Secret Access Key";
const regionName = "My Region";

class S3SignedPolicy {
    constructor() {
        this.bucket = "forecast-post-images";
        this.bucketAcl = "public-read";
        this.expirationStr = this.constructor.createExpDate();
        this.expirationStrClean = this.expirationStr.split(/[:\-.]/g).join("");
        this.amzCred = this.constructor.createAMZCred(this.expirationStrClean);
        this.encodedPolicy = this.constructor.createEncodedPolicy();
        this.sign = this.constructor.createSignedPolicy(this.encodedPolicy, this.expirationStrClean);
    }

    static createExpDate() {
        let expirationDate = new Date();
        console.log("called", expirationDate.toLocaleTimeString());

        expirationDate.setMinutes(expirationDate.getMinutes() + 20);
        const expirationStr = expirationDate.toISOString();

        // const expirationStrClean = expirationStr.split(/[:\-.]/g).join("");
        return expirationStr;
    }

    static createAMZCred(cleanISOString) {
        const YYYYMMDD = cleanISOString.slice(0, 8);
        const amzCred = AccessKeyId + "/" + YYYYMMDD + "/" + regionName + "/s3/aws4_request";

        return amzCred;
    }

    static createSignedPolicy(encodedPolicy, cleanISOString) {
        let YYYYMMDD = cleanISOString.slice(0, 8);
        const kDate = crypto
            .createHmac("sha256", "AWS4" + SecretAccessKey)
            .update(YYYYMMDD)
            .digest("");
        const kRegion = crypto.createHmac("sha256", kDate).update(regionName).digest("");
        const kService = crypto.createHmac("sha256", kRegion).update("s3").digest("");
        const kSigning = crypto.createHmac("sha256", kService).update("aws4_request").digest("");

        const sign = crypto.createHmac("sha256", kSigning).update(encodedPolicy).digest("hex");

        return sign;
    }

    static createEncodedPolicy() {
        const s3Policy = {
            expiration: this.expirationStr,
            conditions: [
                { bucket: this.bucket },
                ["starts-with", "$key", ""], // allows any file name
                { acl: this.bucketAcl },
                ["starts-with", "$Content-Type", "image/"],
                { "x-amz-algorithm": "AWS4-HMAC-SHA256" },
                { "x-amz-credential": this.amzCred },
                { "x-amz-date": this.expirationStrClean },
                { "x-amz-meta-type": "post-image" }
            ],
        };

        let encodedPolicy = Buffer.from(JSON.stringify(s3Policy)).toString("base64");
        return encodedPolicy;
    }
}

请指出我是否在这里遗漏了什么或做错了什么。

标签: javascriptnode.jsamazon-web-servicesamazon-s3

解决方案


原来这不是 AWS 问题,而是我这边的 Javascript 错误。

在我的S3SignedPolicy类中,我已经声明了所有函数,static因此当我this.anything在它们内部调用时,它们将返回undefined,因为this这里指的是 Class ( Function S3SignedPolicy) 而不是创建的单个对象。

因此,我的policy字符串无效。


推荐阅读