来自POST请求的InvalidSignatureException

时间:2018-01-26 04:58:56

标签: reactjs aws-lambda amazon-dynamodb axios aws-api-gateway

我有一个Lambda函数,用于处理从文件(存储在S3存储桶中)中读取数据以及将数据插入Dynamodb表。此Lambda函数使用API​​网关公开为REST端点。该函数接受GET请求以及POST请求。我正在使用axios和aws4(用于签名)库从我的REACT项目发出GET / POST请求。 GET请求是从存储在S3中的文件中读取数据,它的工作正常。 POST请求用于将数据插入Dynamodb表。但是,它不起作用,AWS作为响应返回InvalidSignatureException错误。这是我的代码的摘录:

createAWSSignedRequest(postData) {

    let request = {};

    if (postData) {
        request = {
            host: process.env.AWS_HOST,
            method: 'POST',
            url: process.env.AWS_URL,
            path: process.env.AWS_PATH,
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(postData)
        }
    } else {
        request = {
            host: process.env.AWS_HOST,
            method: 'GET',
            url: process.env.AWS_URL,
            path: process.env.AWS_PATH
        }

    }


    let signedRequest = aws4.sign(request, {
        secretAccessKey: process.env.AWS_SECRET_KEY,
        accessKeyId: process.env.AWS_ACCESS_KEY
    });

    return signedRequest;

}

这就是GET请求的制作方式:

let signedRequest = this.createAWSSignedRequest('GET');

axios(signedRequest)
        .then(response => {



        })
        .catch((error) => {
            console.log("error",error);
        });

这是POST请求的方式:

    const data = {
            uuid: "916b7d90-0137-11e8-94e6-116965754e23", //just a mock value
            date : "22/jan/2018",
            user_response: [
                         {
                            question:"this is quesiton1",
                            choice:"user selected A"
                         },
                         {
                            question:"this is quesiton2",
                            choice: "user selected b"
                         },
                         {
                            question:"this is quesiton3",
                            choice: "user selected C"
                         }
                ]
        };



    let signedRequest = this.createAWSSignedRequest(data);



    axios(signedRequest)
        .then(response => {

           ......

        })
        .catch((error) => {

            console.log("error",error);
        });

如您所见,GET和POST请求的代码完全相同(除了有效负载和方法类型)。我使用相同的秘密访问密钥和两个请求的访问密钥ID进行歌唱。我不确定为什么一个请求导致" InvalidSignatureException"当对方没有。任何人都可以为我解释这个问题。

由于

2 个答案:

答案 0 :(得分:1)

在与AWS4 lib开发人员讨论后,我弄清楚我做错了什么。 AWS4使用“body”作为有效负载属性来计算签名。但是,Axios使用“data”属性作为有效负载。我的错误只是设置其中一个。因此,当我只设置“data”属性时,有效负载存在于请求中,并且正确计算内容长度。但是,签名不正确,因为在计算签名时没有考虑有效载荷。当我只设置“body”时,请求中不存在有效负载,因为Axios不对有效负载使用“body”属性。解决方案是使用有效负载设置两个属性。我希望这对任何遇到同样问题的人都有帮助。

答案 1 :(得分:1)

如果您使用AWS Amplify库,它有一个名为API的模块,它应该适合您的使用案例,并且它将使用经过身份验证或未经身份验证的角色为您执行Sigv4签名。 Auth类别使用Cognito作为默认实现。例如:

npm install aws-amplify --save

然后导入并配置lib:

import Amplify, { API } from 'aws-amplify';
Amplify.configure({
    Auth: {
        identityPoolId: 'XX-XXXX-X:XXXXXXXX-XXXX-1234-abcd-1234567890ab', 
        region: 'XX-XXXX-X'
    },
    API: {
        endpoints: [
            {
                name: "APIName",
                endpoint: "https://invokeURI.amazonaws.com"
            }
        ]
    }
});

然后为您的API Gateway端点调用Lambda:

let apiName = 'MyApiName';
let path = '/path'; 
let options = {
    headers: {...} // OPTIONAL
}
API.get(apiName, path, options).then(response => {
    // Add your code here
});

此处有更多信息:https://github.com/aws/aws-amplify