对 API 网关的 CORS 请求在浏览器中不起作用

Posted

技术标签:

【中文标题】对 API 网关的 CORS 请求在浏览器中不起作用【英文标题】:CORS Request to API Gateway not working in browser 【发布时间】:2021-11-01 12:14:47 【问题描述】:

好吧,我已经准备好看起来很傻了。我敢打赌这是一个简单的问题,我只是没有看到我做错了什么。

我最近部署了一个设置 API 网关的 SAM 应用程序。相关配置如下

# SAM Template Headers + Some Parameters; nothing relating to this.
Resources:

  # The Api Gateway necessary for the authorizers.
  ApiGateway:
    Type: AWS::Serverless::Api
    Properties:
      StageName: !Ref Stage
      Cors: "'*'"
      Auth:
        DefaultAuthorizer: MyCognitoAuthorizer
        Authorizers:
          MyCognitoAuthorizer:
            UserPoolArn: !ImportValue  UserPoolArn
  # some other functions, but one function should do it. 
  # Verified that all functions are referencing the custom ApiGateway resource.
  PutTodosFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: src/handlers/add.putItemHandler
      Description: Adds a todo.
      Policies:
        - DynamoDBCrudPolicy:
            TableName: !Ref TodosTable
      Environment:
        Variables:
          TODOS_TABLE: !Ref TodosTable
          NODE_ENV: !If [isProd, 'production', 'development']
          REGION: !Ref AWS::Region
      Events:
        PutTodo:
          Type: Api
          Properties:
            RestApiId: !Ref ApiGateway
            Path: /
            Method: PUT

这就是我觉得自己快要疯了的地方。如您所见,我的 API Gateway 使用 AWS Cognito 进行授权,因此我使用 Insomnia 桌面应用程序测试流程。

只要我记得提供必要的令牌,所有请求都可以正常工作。在我开始尝试通过浏览器发出相同的请求之前,我认为我是个黄金人。

现在我在尝试发出请求时收到如下错误:

CORS 政策已阻止从源“https://localhost:8080”访问“https://xpquux202j.execute-api.us-west-2.amazonaws.com/alpha/”获取:响应预检请求未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。如果不透明的响应满足您的需求,请将请求的模式设置为“no-cors”以获取禁用 CORS 的资源。

调用它的代码经历了一些迭代,但最近的是:

const headers = new Headers();
    headers.append('Authorization', 'Bearer <JWT Token Goes Here>');

    fetch(API_URL, 
      headers,
      method: 'options', // have tried put/get as well. Neither goes through.
      mode: 'cors' // tried cors and no-cors
    )
      .then(console.log)
      .catch(console.log);

最初出现错误时,我认为 API 网关端的某些内容配置错误,但向端点发出 OPTIONS 请求(在 Insomnia 中)给出:

并在 中测试它

TYIA 寻求帮助;我确定这是我想念的小东西我有点厌倦了试图弄清楚这一点。

【问题讨论】:

从头开始创建自定义 api 网关 + lambda 并使用我的本地应用程序对其进行测试后,答案是 SAM CLI 生成的 OPTIONS 请求启用了 cognito 授权器。它显然需要拥有授权人。我现在正在研究如何解决这个问题。否则就像在 aws 帐户中进入控制台,进入 API 网关,找到选项方法,删除授权者并重新部署 API 一样简单 【参考方案1】:

好的,原来的问题已经解决了……有点。

Tl;博士,您可以在AWS::Serverless::Api 调用的Auth 键中使用AddDefaultAuthorizerToCorsPreflight 选项,例如

  ApiGateway:
    Type: AWS::Serverless::Api
    Properties:
      StageName: !Ref Stage
      Cors: "'*'"
      Auth:
        DefaultAuthorizer: MyCognitoAuthorizer
        AddDefaultAuthorizerToCorsPreflight: false
        Authorizers:
          MyCognitoAuthorizer:
            UserPoolArn: !ImportValue  UserPoolArn

然而,这会产生另一个与 CORS 相关的问题。当您使用此设置创建 API 网关时,OPTIONS 请求的响应中没有 Access-Control-Allow-Headers 标头。我仍在等待 AWS Sam 团队关于 Github 问题的回复:https://github.com/aws/serverless-application-model/issues/2136#issuecomment-915708356

到目前为止,解决方法是简单地从控制台启用 CORS,然后它将具有必要的授权标头。显然不是很好,但也不是特别破坏游戏。

更新

经过一番挖掘,我发现进行这些更改可以使 API 网关部署没有错误。 ApiGateway 资源中的 CORS 部分需要如下所示。

  ApiGateway:
    Type: AWS::Serverless::Api
    Properties:
      StageName: !Ref Stage
      Cors:
        AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
        AllowMethods: "'*'"
        AllowOrigin: "'*'"
      # same Auth: definition as above.

【讨论】:

以上是关于对 API 网关的 CORS 请求在浏览器中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

预检 CORS 请求在 Chrome 60 中不起作用

CORS 在 ASP.NET Web API 2 应用程序中不起作用

CORS 中间件在 nodeJS 中不起作用

对 Kong api 网关端点的基本身份验证请求出现 CORS 错误并且未找到预检

Cors - 如何处理需要自定义标头的预检选项请求? (AWS:使用 vpc 端点的私有 API 网关)

带有 CORS 和 Angular 的 .NET Web API 2 在第一篇文章中不起作用