预检响应中的 Access-Control-Allow-Headers 不允许 AWS API Gateway 返回 access-control-allow-origin

Posted

技术标签:

【中文标题】预检响应中的 Access-Control-Allow-Headers 不允许 AWS API Gateway 返回 access-control-allow-origin【英文标题】:AWS API Gateway returns access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response 【发布时间】:2019-09-09 02:48:02 【问题描述】:

这似乎已经被问了一百万次,但我已经尝试添加到我的前端(React)和后端(带有 Node.js 的 Lambda):

Access-Control-Allow-Headers
Access-Control-Request-Headers
Access-Control-Allow-Methods: 'GET,PUT,POST,DELETE,PATCH,OPTIONS'

但我仍然收到此错误:

Access to XMLHttpRequest at 'https://<API-INVOKE-URL>/prod/notes' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.

这是我处理响应的 Lambda 代码:

function buildOutput(statusCode, data) 
    let _response = 
        statusCode: statusCode,
        headers: 
            "Access-Control-Allow-Origin": "*"
        ,
        body: JSON.stringify(data)
    ;
    return _response;
;

这是我发送 POST 请求的 React 代码:

createNote(note) 
        return API.post("notes", "/notes", 
            headers: 
                "Authorization": this.state.token,
                "Access-Control-Allow-Origin": "*"
            ,
            body: 
                userid: this.state.username,
                noteid: 'new',
                content: 'from frontend'
            
        );
我已经从控制台测试了我的 Lambda 函数并且它可以工作(能够对 DynamoDB 执行 CRUD)。 我已经为我的 API Gateway 资源启用了 CORS 并部署了 API。 我尝试过使用 PostMan:
Headers:Content/Type: application/json
Authorization: <MY_TOKEN>
*With and without* Access-Control-Allow-Origin: *

它有效:请求已成功从 PostMan 发送到 API Gateway,从而在我的 DynamoDB 中生成一个新项目。

【问题讨论】:

我认为您必须允许标头来源以及来自后端的 API 响应。 我试过了。这也行不通。 【参考方案1】:

实际上在 header 中添加一些数据会将 POST 请求转换为 OPTIONS。 因此,它将触发请求:

1) 使用 OPTIONS 方法

2) OPTIONS 请求成功响应后,将进行实际的 API 调用。

要处理 CORS,您应该在后端使用 this。

【讨论】:

【参考方案2】:

只是为了解决这个问题。一些浏览器会对您的端点进行“预检”检查。这意味着在进行您期望的 POST 方法调用之前,将使用 OPTIONS 方法调用您的端点。在 AWS 中,转到 API Gateway 并创建一个新资源,选中 Create Options 选项,这将创建您需要添加到终端节点的默认响应标头。

【讨论】:

【参考方案3】:

CORS 需要客户端和服务器之间的直接连接。出于安全原因,您的浏览器可能会阻止连接。

HTTP 与 HTTPS

我也会尝试在您的浏览器上启用下载。

我相信您还应该在授权标头中将不记名添加到您的令牌中,例如:

'持有者 TOKEN_VALUE'

【讨论】:

【参考方案4】:

谢谢各位。 我赞成您的回答/建议。我相信它们在大多数情况下都会有所帮助。我已经弄清楚为什么会出现这个错误。

我的错:我有这两种资源:

/notes/ (method: any)
/notes/noteid (method: any)

并且调用 URL 在 AWS API Gateway 中实际上是 &lt;path&gt;/notes/noteid(字符串中包含 )。我以为它会像/notes/:noteid

所以前端代码应该是这样的:

return API.post("notes", "/notes/noteid", ...

【讨论】:

以上是关于预检响应中的 Access-Control-Allow-Headers 不允许 AWS API Gateway 返回 access-control-allow-origin的主要内容,如果未能解决你的问题,请参考以下文章

预检响应没有 HTTP ok 状态。 Angular 6 中的 403

OAuth 中的 CORS:对预检请求的响应未通过访问控制检查

预检响应中的 Access-Control-Allow-Headers 不允许授权

预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段内容类型

预检响应中的 Access-Control-Allow-Header 中的允许请求标头字段

预检响应中的 Access-Control-Allow-Methods 不允许方法 PATCH