如何使用包含凭证的fetch和POST请求发送数据?

时间:2019-04-11 13:36:42

标签: javascript node.js reactjs cors fetch

我想使用获取将来自JSON的一些数据从端口3000上的React前端使用fetch发送到3005上的node.js服务器。我在服务器上配置了cors,但是每次尝试使用Cookie发送请求时, Chrome抛出错误:

  

从原点“ http://localhost:3005/user-connected”到“ http://localhost:3000”处获取的访问已被CORS策略阻止:对预检请求的响应未通过访问控制检查:“访问控制”的值当请求的凭据模式为“包括”时,响应中的-Allow-Origin'标头不得为通配符'*'。

服务器代码中的所有console.log都将被跳过。

当我在提取代码中删除标头时

  

“内容类型”,“应用程序/ json”

我得到了cookie,但是没有数据。有了此标头,但没有凭据:“ include”,我可以获取数据,但永远不会同时获取两者。

这是我的提取代码:

fetch("http://localhost:3005/user-connected", {
            mode: "cors",
            method: "post",
            headers: [
                ["Content-Type", "application/json"],
            ],
            credentials: "include",
            body: JSON.stringify({data: "123"})
        })
            .then(data => data.json())
            .then((data) => {
               console.log(`Response: ${JSON.stringify(data)}`);
            }).catch(err => {
                console.log(`Error: ${err}`)
        });

Node.js核心配置:

app.use(cors({credentials: true}));

app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type', 'Access-Control-Allow-Origin', 'Origin');
  res.setHeader('Access-Control-Allow-Credentials', true);
  next();
});

我的发帖路线:

let cookiesData = (req, res) => {
  console.log(`Cookie user-connected: ${req.cookies.io}`)


  console.log(`Received data: ${JSON.stringify(req.body)}`);
  res.send({ status: "OK" });
}

router.post("/user-connected", cors({origin: 'http://localhost:3000'}), cookiesData);

是否有可能做我想做的事情?还是我错过了一些重要的配置?

4 个答案:

答案 0 :(得分:0)

尝试将标头用作对象:

headers: {
    "Content-Type": "application/json",
},

文档Fetch Reference - Headers显示的是带有对象而非数组的示例

答案 1 :(得分:0)

每当在前端和后端之间的连接过程中发生错误时,通常最好将问题分成这些前端,因此首先让我们完全忽略前端。相反,我们可以使用curl或Postman查询后端,通过它您可以深入了解服务器实际返回的内容。

现在,在您的情况下,CORS飞行前请求很重要,可以通过将OPTIONS请求发送到特定服务器路径来检查它是否正确设置。

然后您将发现Wildcards and credentials can't be used at the same time

现在,如果您更改路线本身的cors({ ... })选项,您会发现这不会影响返回的实际OPTIONS标头。也就是说,由于第一个cors()将终止所有OPTION请求并使用uts配置进行响应,因此所有其他cors()中间件都将保持不变。

因此,您应该之一添加一个全局cors处理程序:

  app.use(cors({origin: 'http://localhost:3000', credentials: true }));
 // don't use cors() again!

或(可能会更好,因为它允许进行细粒度的访问控制)将cors设置自行添加到每个路由:

 app.use("/route", cors({origin: 'http://localhost:3000'}));
 app.get("/route", (req, res) => { /*...*/ });

您还可以将其添加到路由器,以便cors策略仅影响特定路径。

答案 2 :(得分:0)

您需要在获取请求的post方法中传递这样的标头:

{
  credentials: 'include',
  mode: 'cors',
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
}

您必须确保已为localhost:3000授予访问权限来源

答案 3 :(得分:0)

添加Content-Type将首先触发预检请求,然后再发送实际请求。飞行前请求方法为OPTIONS。 OPTIONS在请求标头中不包含cookie(至少对于Chrome和Firefox)。

该错误可能是由于以下代码造成的:

console.log(`Cookie user-connected: ${req.cookies.io}`)

req.cookies在预检请求期间为null,并且在您尝试获取req.cookies.io时将引发错误。印前检查请求要求服务器返回200(请参阅https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Preflighted_requests)。您的错误代码可能抛出500,从而向您显示可怕的CORS错误消息。

您必须先处理飞行前请求。

在服务器端,尝试处理CORS代码中的OPTIONS方法以在next()之前返回200:

app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type', 'Access-Control-Allow-Origin', 'Origin');
  res.setHeader('Access-Control-Allow-Credentials', true);

  if (req.method === 'OPTIONS') {
    res.sendStatus(200);
    return;
  }

  next();
});

这将防止在预检请求期间执行next()任何代码,并告知客户端可以发送实际请求。