修复 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 CDK 为 AWS API 网关启用 CORS