Node.js:POST - 请求方法:OPTIONS 状态代码:403 Forbidden

Posted

技术标签:

【中文标题】Node.js:POST - 请求方法:OPTIONS 状态代码:403 Forbidden【英文标题】:Node.js : POST - Request Method: OPTIONS Status Code: 403 Forbidden 【发布时间】:2018-09-08 19:11:07 【问题描述】:

我们有以下设置:

Front end code : REACT (Hosted using express js) (lets call this www.domainA.com)
Backend        : .NET WEB API (Hosted in IIS 7.5) (lets call this www.domainB.com)

FE 应用的域正在向 Web api 发出 GET 数据和 POST 数据的请求。

GET 运行良好,但是每当我尝试将数据发布到 Web API 时,它都会引发以下错误:

Request URL: http://www.domainB.com/api/postdataoperation
Request Method: OPTIONS
Status Code: 403 Forbidden

我查看了许多 CORS 文章并继续在 IIS 中设置 HTTPResponseHeaders,如下所示:

Access-Control-Allow-Methods : POST,GET,OPTIONS,PUT,DELETE
Access-Control-Allow-Origin  : http://www.domainA.com

react 解决方案的 post 请求如下:

axios.post(`http://www.domainB.com/api/postdataoperation`, userId);

【问题讨论】:

所以我理解正确,您在 IIS 中托管节点服务器? @TheIncorrigible1 很抱歉错过了 FE 托管在 Express 上的详细信息(更新) 您在浏览器控制台中看到了什么?它会给您一个错误,告诉您请求/CORS 标头的问题所在。请将该信息添加到您的问题中,因为它对解决方案至关重要 你在用csrf_token吗? 你写过Node.js服务器吗?如果是,那么您能否与我们分享接受GETPOST 请求的路线部分。这将更清楚问题是什么。此外,您可以查看Node.js 服务器日志,以找到确切的错误。 【参考方案1】:

问题在于您的服务器未配置为以正确的响应状态(2xx 成功状态)响应 OPTIONS 请求。

GET 工作正常,因为它没有发出预检请求,因为它符合simple request 定义的条件CORS documentation

另一方面,POST 请求符合Preflighted request 的条件,这意味着应首先发出预检 OPTIONS 请求。

简而言之,您已经正确设置了 CORS 响应标头,但服务器未配置为响应 OPTIONS 方法请求的 2xx 响应(通常为 200 状态)。

服务器必须以 2xx 成功状态(通常为 200 或 204)响应 OPTIONS 请求。

如果服务器不这样做,那么您将其配置为发送什么 Access-Control-* 标头没有任何区别。配置服务器以正确方式处理 OPTIONS 请求(发送 200 或 204 成功消息)的答案取决于它运行的服务器软件

从this answer 借用解决方案,在您的后端执行此操作,.NET WEB API:

在您的 BaseApiController.cs 中:

我们这样做是为了允许 OPTIONS http 动词

public class BaseApiController : ApiController
  
    public HttpResponseMessage Options()
    
      return new HttpResponseMessage  StatusCode = HttpStatusCode.OK ;
    

参考文献

Preflighted requests

response for preflight 403 forbidden

注意

在 domainA.com 上运行 nodejs 服务器是无关紧要的。 "axios" 库可用于 a) 从浏览器发出 XMLHttpRequest 或 b) 从 node.js 发出 http 请求。在这种情况下,它是第一个选项,到 domainB 的“axios.post”是通过来自浏览器的 XMLHttpRequest 完成的,这就是为什么您会在 domainB.com 获得 预检请求。

【讨论】:

【参考方案2】:

Jannes Botis 的回答很好地解释了预检机制。我只是在 Node.js / Express 上添加用于解决此问题的代码

const express = require('express');
const app = express();

app.use((req, res, next) => 
  res.setHeader('Access-Control-Allow-Origin', 'http://www.domainA.com');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
  res.setHeader(
    'Access-Control-Allow-Headers',
    'Origin, X-Requested-With, Content-Type, Accept, Authorization'
  );
  next();
);

// All OPTIONS requests return a simple status: 'OK'
app.options('*', (req, res) => 
  res.json(
    status: 'OK'
  );
);

app.get('/', ...);

app.post('/api/postdataoperation', ...);

【讨论】:

以上是关于Node.js:POST - 请求方法:OPTIONS 状态代码:403 Forbidden的主要内容,如果未能解决你的问题,请参考以下文章

node.js之路由,中间件,ge请求和post请求的参数

Node.js + Express 接口请求(GETPOSTPUT)事例

Node.js GET/POST请求

Node.js GET/POST对应的url/query-string常用的方法介绍

通过 POST 请求将数据从 node.js 服务器发送到 node.js 服务器

通过 POST 请求将数据从 node.js 服务器发送到 node.js 服务器