【问题标题】:CORS on AWS API Gateway and S3AWS API Gateway 和 S3 上的 CORS
【发布时间】:2020-06-05 18:03:46
【问题描述】:

我正在调用一个使用 lambda 函数的 AWS API。我从托管在 S3(静态 Web 托管)中的 HTML 页面调用它。调用 API 时出现 CORS 错误:

在 '' 从源访问 XMLHttpRequest '' 已被 CORS 策略阻止:否 请求中存在“Access-Control-Allow-Origin”标头 资源。

我在 API 上启用了 CORS,在 S3 存储桶上指定 CORS 后尝试过,但它不起作用。 看来,我错过了指定 CORS 标头的正确位置。

附加信息: 我在 chrome 开发者工具中得到以下信息

**Response Headers**
content-length: 42
content-type: application/json
date: Mon, 24 Feb 2020 04:28:51 GMT
status: 403
x-amz-apigw-id: IYmYgFQvoAMFy6Q=
x-amzn-errortype: MissingAuthenticationTokenException
x-amzn-requestid: 79b18379-383d-4ddb-a061-77f55b5727c3

**Request Headers**
authority: apiid-api.us-east-1.amazonaws.com
method: POST
path: /Prod
scheme: https
accept: application/json, text/javascript, */*; q=0.01
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9,hi;q=0.8
access-control-allow-headers: Origin, X-Requested-With, Content-Type, Accept, Authorization
access-control-allow-methods: GET, OPTIONS
access-control-allow-origin: https://apiid.execute-api.us-east-1.amazonaws.com/Prod
content-length: 117
content-type: application/json; charset=UTF-8
origin: http://example.com
referer: http://example.com/
sec-fetch-mode: cors
sec-fetch-site: cross-site
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36

Lambda 函数代码:

var AWS = require('aws-sdk');
var ses = new AWS.SES();

var RECEIVER = 'example@gmail.com';
var SENDER = 'example@gmail.com';

var response = {
 "isBase64Encoded": false,
 "headers": { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*'},
 "statusCode": 200,
 "body": "{\"result\": \"Success.\"}"
 };

exports.handler = function (event, context) {
    console.log('Received event:', event);
    sendEmail(event, function (err, data) {
        context.done(err, null);
    });
};

function sendEmail (event, done) {
    var params = {
        Destination: {
            ToAddresses: [
                RECEIVER
            ]
        },
        Message: {
            Body: {
                Text: {
                    Data: 'name: ' + event.name + '\nphone: ' + event.phone + '\nemail: ' + event.email + '\ndesc: ' + event.desc,
                    Charset: 'UTF-8'
                }
            },
            Subject: {
                Data: 'Website Referral Form: ' + event.name,
                Charset: 'UTF-8'
            }
        },
        Source: SENDER
    };
    ses.sendEmail(params, done);
}

【问题讨论】:

标签: amazon-web-services cors


【解决方案1】:

请求的资源上不存在“Access-Control-Allow-Origin”标头。

这表示您请求的资源(通过 API 网关的 Lambda)在其响应中未返回 Access-Control-Allow-Origin 标头;浏览器在来自 API 的响应中期待 CORS 标头(可能是因为 OPTIONS 请求),但响应中没有它们。

您没有具体说,但我假设您在 API 网关上使用 Lambda 代理集成。要解决您的问题,请将 Access-Control-Allow-Origin: * 标头添加到您的 Lambda 返回的响应中。您没有指定编写 Lambda 的语言,也没有提供您的 Lambda 代码,但如果它是在 NodeJS 中,您将返回的 sn-p 可能类似于:

    const result = {
        statusCode: 200,
        headers: {
            'Access-Control-Allow-Origin': '*',
            // other required headers
        },
        body: object_you_are_returning
    };

    return result;

【讨论】:

  • 感谢您的回复。我签入了我的 Lambda 函数。它是用 Node.js 编写的,并且 header 以以下格式指定:var response = { "isBase64Encoded": false, "headers": { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*'}, "statusCode": 200, "body": "{\"result\": \"Success.\"}" };
  • 我查看了它,您确实已经建立了响应,但是您在发送电子邮件后没有将其返回给调用者。
  • 现在我得到Access to XMLHttpRequest at 'https://apiid.execute-api.us-east-1.amazonaws.com/Prod' from origin 'http://example.com' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.,无论我是否在函数中添加return。
  • 看起来您的原始问题已解决,这是一个新错误...在您的 OPTIONS 请求中,您可能不允许使用标头。
  • 知道哪个是指定选项的正确位置吗?我很困惑,因为有很多地方可以指定 OPTIONS (1) 网页的 js 文件 (2) S3 存储桶上的 CORS 配置 (3) API 网关上的 CORS 配置和 (4) Lambda 函数 (Node.js) 上的标头.我做了几次打击和跟踪,但没有奏效。
【解决方案2】:

非常令人惊讶的是,原因似乎是“客户端不应该有'Access-Control-Allow-Origin':'*'。显然,这应该只存在于 Lambda 代码中,并且将其添加到 jQuery 代码中会导致预检由于某种原因而失败。” https://github.com/serverless/serverless/issues/4037#issuecomment-320434887

在评论后补充信息:

我还尝试使用托管在 S3 中的 ajax 通过 API Gateway 调用我的 Lambda 函数。我尝试了很多建议,尤其是这个解决方案 (http://stackoverflow.com/a/52683640/13530447),但没有一个对我有用。在 Chrome 的开发者模式下,我一直看到错误 "Access to XMLHttpRequest at '[my API]' from origin '[my S3 website]' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response." 我通过在 ajax 中删除 'Access-Control-Allow-Origin': '*' 解决了这个问题。还是以解决方案(http://stackoverflow.com/a/52683640/13530447)为例,改一下就行了

$.ajax(
{
    url: 'https://npvkf9jnqb.execute-api.us-east-1.amazonaws.com/v1',
    headers: {'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*'
},
    crossDomain: true,
    type:'GET',
    dataType: 'text',
    success: function(data)
    {
        window.alert(data);
    }
}); 

进入

$.ajax(
{
    url: 'https://npvkf9jnqb.execute-api.us-east-1.amazonaws.com/v1',
    headers: {'Content-Type': 'application/json'},
    crossDomain: true,
    type:'GET',
    dataType: 'text',
    success: function(data)
    {
        window.alert(data);
    }
});

【讨论】:

  • 欢迎来到 StackOverflow,如果需要理解答案,请添加更多描述和代码,因为它会尽快解决其他人的问题
  • 感谢您的提醒。好吧,我还尝试使用托管在 S3 中的 ajax 通过 API Gateway 调用我的 Lambda 函数。我尝试了很多建议,尤其是这个解决方案 (stackoverflow.com/a/52683640/13530447),但没有一个对我有用。在 Chrome 的开发人员模式下,我一直看到错误“从源 '[my S3 website]' 访问 XMLHttpRequest 在 '[my API]' 已被 CORS 策略阻止:请求标头字段 access-control-allow-origin 是Access-Control-Allow-Headers 在预检响应中不允许。”我通过删除 'Access-Control-Allow-Origin': '*' in ajax 解决了这个问题。
猜你喜欢
  • 2017-02-27
  • 2017-09-19
  • 2018-01-13
  • 2018-03-22
  • 1970-01-01
  • 2019-01-07
  • 2019-09-24
  • 2016-09-12
  • 2021-09-15
相关资源
最近更新 更多