修复 AWS API 网关不存在的 CORS“对预检的响应 ...”标头并放大

Posted

技术标签:

【中文标题】修复 AWS API 网关不存在的 CORS“对预检的响应 ...”标头并放大【英文标题】:Fix CORS "Response to preflight..." header not present with AWS API gateway and amplify 【发布时间】:2020-07-03 20:04:29 【问题描述】:

我一直在为以下错误苦苦挣扎。我已经尝试了很多教程和 *** 答案,但没有一个解决方案可以解决我的问题。

访问 XMLHttpRequest 在 'https://xxx' 来自原点 'http://localhost:3000' 已被 CORS 策略阻止:响应 预检请求未通过访问控制检查:否 请求中存在“Access-Control-Allow-Origin”标头 资源。

我正在使用 SAM 无服务器来创建我的 api。

template.yaml:

Globals:
  Function:
    Timeout: 10
  Api:
    Cors:
      AllowMethods: "'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'"
      AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
      AllowOrigin: "'*'"

我的 lambda 函数: 我的 GET 响应和 OPTIONS 响应都返回了以下标头:

headers: 
  "Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'",
  "Access-Control-Allow-Origin": "'*'",
  "Access-Control-Allow-Methods": "'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'"

我的 API 使用 amplify 进入我的 ReactJs 应用程序:

API.get(apiName, path, 
   headers: 
      "Access-Control-Allow-Origin": "*",
      // "Access-Control-Allow-Headers": "Content-Type,X-Amz-Date,Authorization,X-Api-Key,x-requested-with",
      // "Access-Control-Allow-Methods": "OPTIONS,POST,GET,PUT,DELETE",
      // 'Content-Type': 'application/json'
   
)

我已经在我的 template.yaml、我的 lambda 函数和我的 reactJs 项目中尝试了 Access-Control-Allow-Headers、Access-Control-Allow-Methods 的所有组合。

这是我在 API 端点上调用 postman 中的选项时的结果。因此,我确实得到了正确的标头,因此根据我的理解,我的 API 允许 CORS。

【问题讨论】:

如果您在选项请求中省略“x-api-key”标头会怎样? @JannesBotis 在邮递员中我得到“禁止”,但在我的应用程序中,我得到了我的问题中列出的相同错误(CORS 错误)。 在这种情况下,您能否回复 200 状态和 cors 标头?检查***.com/questions/58547499/… 和***.com/a/49959851/4448410 @JannesBotis 我不确定你的意思。当我有“x-api-key”标头时,我确实收到了 200 OK 状态和 cors 标头,但是当我删除“x-api-key”标头时,我得到了 403 Forbidden 而没有 cors 标头。 使选项在没有“x-api-key”的情况下也能正常工作 【参考方案1】:

因此,在与 @Jannes Botis 进行了非常有益的讨论后,我找到了解决方案。

在 template.yaml 中,我将值更改为:

Globals:
  Function:
    Timeout: 10
  Api:
    Cors:
      AllowMethods: "'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'"
      AllowHeaders: "'Content-Type,X-Amz-Date,X-Amz-Security-Token,Authorization,X-Api-Key,X-Requested-With,Accept,Access-Control-Allow-Methods,Access-Control-Allow-Origin,Access-Control-Allow-Headers'"
      AllowOrigin: "'*'"

  MyAPIFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: myendpoint/
      Handler: app.lambdaHandler
      Runtime: nodejs12.x
      Events:
        GetMyData:
          Type: Api
          Properties:
            RestApiId: !Ref MyApi
            Path: /myendpoint
            Method: get
        Options:
          Type: Api
          Properties:
            RestApiId: !Ref MyApi
            Path: /myendpoint
            Method: options
            Auth:
              ApiKeyRequired: false

注意:您将收到错误消息“请求的资源上不存在 'xxx' 标头。”其中 xxx 是 Access-Control-Allow-Methods、Access-Control-Allow-Origin 和 Access-Control-Allow-Headers,因此您需要将它们添加到 AllowHeaders 中。另请注意,您必须使用 ApiKeyRequired: false 添加 Options 资源。

那么你的选项和获取请求的响应应该有相同的标题:

headers: 
    "Access-Control-Allow-Headers": "Content-Type,X-Amz-Date,X-Amz-Security-Token,Authorization,X-Api-Key,X-Requested-With,Accept,Access-Control-Allow-Methods,Access-Control-Allow-Origin,Access-Control-Allow-Headers",
    "Access-Control-Allow-Origin": "*",
    "Access-Control-Allow-Methods": "DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT",
    "X-Requested-With": "*"

注意:“接受”必须存在,否则您将收到“对预检请求的响应未通过访问控制检查:它没有 HTTP ok 状态。”。

当您在邮递员中省略 x-api-key 时,您的预检必须能够通过 200 OK。

【讨论】:

CDK 用户,您的corsPreflight 参数中必须有allowHeaders:['Content-Type', 'X-Amz-Date', 'X-Amz-Security-Token', 'Authorization', 'X-Api-Key', 'X-Requested-With', 'Accept', 'Access-Control-Allow-Methods', 'Access-Control-Allow-Origin', 'Access-Control-Allow-Headers'] 我使用的是AWS HTTP API Gateway,如何在AWS HTTP API Gateway中解决?【参考方案2】:

我包含此响应,以防有人仍然因此错误而拉扯头发。我花了一天的时间试图弄清楚这一点 - 阅读有关 CORS 的所有内容,甚至将我的代码迁移到新的 AWS HttpAPI(无论如何这可能是一件好事)。 最重要的是,我一直关注错误消息:

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

这可能会为您指明错误的方向。我的问题与“Access-Control-Allow-Origin”标题无关。事实上,我的问题的答案非常简单,我发送了一个 JWT 令牌作为“授权”标头的一部分,并且我的响应中没有包含“访问控制允许标头”条目 - 呃! (但如果错误消息更准确,那就太好了......)

如果您正在阅读本文,您可能已经在网络上找到了许多很好的信息来源,但这个网站对我非常有用:www.test-cors.org

【讨论】:

【参考方案3】:

如果有人在 nodejs 中使用 serverless 并面临 cors-policy 的 prelight 问题,这里是简单的解决方案 ...

functions:
  externalHandler:
    handler: handler.handlerExport
    events:
      - http:
          path: handlerPath
          method: post
          cors:
            origin: '*' # <-- Specify allowed origin
            headers: # <-- Specify allowed headers
              - Content-Type
              - X-Amz-Date
              - Accept
              - Authorization
              - X-Api-Key
              - X-Amz-Security-Token
              - X-Amz-User-Agent
            allowCredentials: false

在处理程序文件中

如果您使用的是快递

...
const app = express();
app.use(function (req, res, next) 
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Credentials", true);
  res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS");
  res.header(
    "Access-Control-Allow-Headers",
    "x-www-form-urlencoded, Origin, X-Requested-With, Content-Type, Accept, Authorization"
  );
  next();
);
...

一般来说

  const response = 
    statusCode: 200,
    headers: 
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Credentials': true,
    ,
    body: JSON.stringify(
      product: product
    ),
  ;

更多信息请参考serverless article

【讨论】:

【参考方案4】:

如果您尝试访问不存在的 URL,也会发生此错误。哦。 在进入 CORS 地狱之前,请先确认请求 URL 确实正确,并且您要访问的资源正在运行。

就我而言,我试图通过错误的 Lightsail URL 访问后端。向这个不正确的 URL 发送 POST 请求会触发 CORS 错误。使用正确的 URL 访问后端修复了错误。

【讨论】:

以上是关于修复 AWS API 网关不存在的 CORS“对预检的响应 ...”标头并放大的主要内容,如果未能解决你的问题,请参考以下文章

React.js - CORS 策略:请求的资源上不存在“Access-Control-Allow-Origin”标头。 [AWS - Lambda - API 网关]

AWS API 网关 CORS [关闭]

使用 AWS CDK 为 AWS API 网关启用 CORS

从帖子正文读取时,AWS API 网关 CORS 错误

如何使用 AWS API 网关和 Lambda 通过 CORS?

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