12

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

从源“ http://localhost:3000 ”访问“ https://xxx ”的 XMLHttpRequest已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:没有“访问控制允许来源” ' 请求的资源上存在标头。

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

模板.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 使用放大进入我的 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。 在此处输入图像描述

4

4 回答 4

10

因此,在与@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。

于 2020-03-25T13:31:51.910 回答
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

于 2020-11-12T14:43:54.380 回答
0

如果有人在 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
    }),
  };

有关更多信息,请参阅无服务器文章

于 2020-12-25T12:18:36.747 回答
0

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

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

于 2021-07-14T09:55:52.300 回答