将 fetch 与 Express、React、cors、cookie 一起使用 - “Access-Control-Allow-Origin”标头

Posted

技术标签:

【中文标题】将 fetch 与 Express、React、cors、cookie 一起使用 - “Access-Control-Allow-Origin”标头【英文标题】:Using fetch with Express, React, cors, cookies - 'Access-Control-Allow-Origin' header 【发布时间】:2020-12-01 04:26:57 【问题描述】:

花了很多时间试图解决这个问题,但没有成功。我正在尝试使用 cookie 运行 csurf 保护。目前我已经尽可能地简化了以下代码。我正在运行从 React 到 Express 上的另一台服务器的获取请求。它给出了错误:

“CORS 策略已阻止从源 'http://localhost:3003/testlogin' 获取的访问权 'http://localhost:3000':否 'Access-Control-Allow-Origin'请求的资源上存在标头。如果不透明的响应满足您的需求,请将请求的模式设置为“no-cors”以获取禁用 CORS 的资源。”

据我了解,“Access-Control-Allow-Origin”标头是在我的 corsOptions 中设置的。所以它不应该抛出这个错误。我显然错过了一些东西。感谢您提供任何帮助。

快递服务器:

const cookieParser = require("cookie-parser");
const cors = require('cors')
const express = require("express");
const csrf = require("csurf");

const app = express();

const csrfMiddleware = csrf( cookie: true );

app.use(cookieParser());

const corsOptions = 
  origin: 'http://localhost:3000',   
  methods: "GET,HEAD,POST,PATCH,DELETE,OPTIONS",
  credentials: true,               
  allowedHeaders: "Content-Type, Authorization, X-Requested-With, Accept",

app.options('*', cors(corsOptions))

app.use(csrfMiddleware);

app.post("/testlogin", cors(corsOptions), (req, res) => 
  console.log('test login reached', );
  res.end(JSON.stringify( status: "success" ));
);

const PORT = process.env.PORT || 3003;
app.listen(PORT, () => 
  console.log(`Listening on http://localhost:$PORT`);
);

前端(反应):

function testClick() 
  console.log("testClick Clicked");

  let urlToGetUserProfile = 'http://localhost:3003/testlogin'

  return fetch(urlToGetUserProfile, 
    method: "POST",
    headers: 
      Accept: "application/json",
      "Content-Type": "application/json",
    ,
    credentials: "include",
    body: JSON.stringify( idToken: "idTokengoeshere" ),
  )
    .then((fetchResponse) => 
      console.log(fetchResponse);
    )

【问题讨论】:

【参考方案1】:

csrfMiddleware 中间件函数在 cors 中间件之前被调用。

它会抛出 ForbiddenError: invalid csrf token 以阻止 cors 中间件将标头添加到响应中。

您可以通过将cors 中间件放在首位来解决这个问题。

app.use(cors(corsOptions));
app.use(csrfMiddleware);

app.post("/testlogin",(req, res) => 
  console.log('test login reached', );
  res.end(JSON.stringify( status: "success" ));
);

【讨论】:

啊太棒了。这似乎已经停止了 CORS 问题。我现在在我的服务器中收到一个错误:“ForbiddenError: invalid csrf token”你不会知道这个问题吧? 大概,您没有针对http://localhost:3003/ 存储在浏览器中的带有 CSRF 令牌的 cookie。您也没有任何标题或正文中的令牌。 在我的请求标头中我得到: Cookie: _csrf=wgyr7qT7wY-nLAVGTLgz80Kx 所以看起来它正在发送?在我的开发人员工具中,_csrf cookie 也显示出来了。域是'localhost',路径是'/'。 OK,所以是请求的正文或标头中缺少匹配的令牌。

以上是关于将 fetch 与 Express、React、cors、cookie 一起使用 - “Access-Control-Allow-Origin”标头的主要内容,如果未能解决你的问题,请参考以下文章

使用 Multer 将带有 fetch 的图像上传到 Express

使用 react js 和 express API 服务器发布一个带有 fetch 的对象

React Express Fetch Post CORS 错误:对预检请求的响应未通过访问控制检查:它没有 HTTP ok 状态

如何使用 React.js 中的 Fetch API 将数据发布到数据库

前端(React)如何与后端(Express)交互?

将 Express.js 与 React.js 一起使用的推荐方式?