表达Cors缺少允许凭据

3
我为我的Express服务器配置了以下内容:
import express from "express";
import bodyParser from "body-parser";
import mongoose from "mongoose";
import cors from "cors";
import dotenv from "dotenv";
import helmet from "helmet";
import morgan from "morgan";
import cookieParser from "cookie-parser";
import categoryRoutes from "./routes/category.js";
import subCategoryRoutes from "./routes/subCategory.js";
import expenseRoutes from "./routes/expense.js";
import userRoutes from "./routes/user.js";
import { authMiddleware } from "./middleware/authMiddleware.js";

dotenv.config();

const app = express();
app.use(cookieParser());
app.use(express.json());
app.use(helmet());
app.use(helmet.crossOriginResourcePolicy({ policy: "cross-origin" }));

app.use(morgan("common"));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(
  cors({
    origin: *********************,
    credentials: true,
  })
);

app.use("/category", authMiddleware, categoryRoutes);
app.use("/subCategory", authMiddleware, subCategoryRoutes);
app.use("/expense", authMiddleware, expenseRoutes);
app.use("/user", userRoutes);

const PORT = process.env.PORT || 9000;

mongoose
  .connect(process.env.MONGO_URL, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  })
  .then(async () => {
    app.listen(PORT, () => {
      console.log(`Server running on port: ${PORT}`);
    });
  })
  .catch((error) => {
    console.log(`${error} connecting to DB`);
  });

但是对于任何不是“/user”的路由,我都会收到一个“CORS缺少允许凭据”错误,并且请求头如下:
Accept
    */*
Accept-Encoding
    gzip, deflate, br
Accept-Language
    en-US,en;q=0.5
Connection
    keep-alive
Cookie
    jwt=*************************
Host
    *************************
Origin
    https://*********************
Referer
    https:/**********************/
Sec-Fetch-Dest
    empty
Sec-Fetch-Mode
    cors
Sec-Fetch-Site
    cross-site
TE
    trailers
User-Agent
    Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0

我在其他路由中使用了一个中间件,可能会导致问题, 如果是这样的话,这里是它的代码:
import jwt from "jsonwebtoken";

export const authMiddleware = async (req, res, next) => {
  const { id, token } = req.cookies;
  console.log(id, token);
  try {
    if (id) {
      req.userId = id;
    res.setHeader(
      "Access-Control-Allow-Origin",
      "**************************"
    );
    res.setHeader("Access-Control-Allow-Credentials", true);
      next();
    }

    if (token) {
      const decoded = jwt.verify(token, process.env.JWT_SECRET);
      if (decoded) {
        const userId = decoded.id;
        req.userId = userId;
    res.setHeader(
      "Access-Control-Allow-Origin",
      "**************************"
    );
    res.setHeader("Access-Control-Allow-Credentials", true);
        next();
      }
    }
  } catch (error) {
    throw new Error("Not authorized!");
  }
};

我觉得我的跨域资源共享(CORS)和头盔(Helmet)配置可能设置不正确,但这是我访问的一个端点,它的响应中没有设置任何头部信息。
router.get("/expenses/", async (req, res) => {
  const userId = req.userId;
  console.log(userId);

  try {
    const expenses = await Expense.find({
      userId: userId,
    })
      .populate("subCategory")
      .populate("category")
      .exec();

    const mappedExpenses = expenses.map((expense) => ({
      id: expense._id,
      date: expense.date,
      price: expense.price,
      userId: expense.userId,
      category: expense.category.name,
      subCategory: expense.subCategory.name,
    }));
    console.log("user expenses: ", mappedExpenses);
    res.status(200).json(mappedExpenses);
  } catch (error) {
    res.status(404).json({ message: error.message });
  }
});

可能有用的是补充一下,我在/expense/expenses请求上遇到了502错误网关和严格的来源-跨源引荐策略。
最后,我正在使用rtk query来进行这些API调用,基本查询如下:
baseQuery: fetchBaseQuery({baseUrl: import.meta.env.VITE_BASE_URL, credentials: 'include'}),

环境变量与服务器URL匹配,所以没有问题,前端登录组件会设置cookie,如下所示:
loginUser(values)
            .unwrap()
            .then((res) => {
              console.log(res._id);
              setCookie("id", res._id, {
                path: "/",
                sameSite: "none",
                secure: true,
              });

              toast.success("logged in!");

              navigate("/dashboard", { replace: true });
            })
            .catch((e) => {
              console.log(e);
            });

1
不要将cors模块与自己编写的setHeader调用混合使用,用于处理Access-Control-etc头部。这样只会让事情变得更加混乱。 - Quentin
1
不要将cors模块与自己编写的setHeader调用混合使用,用于处理Access-Control-etc头部。这样只会让事情变得更加混乱。 - Quentin
1
我强烈建议使用cors模块而不是自己编写CORS实现。 - Quentin
1
我强烈建议使用 cors 模块而不是自行开发 CORS 实现。 - Quentin
更新:这是我的中间件的问题。如果我不使用trycatch并手动设置userId,数据就会正常获取。这意味着问题出在cookies上,很可能是未定义的。 - Mathew
显示剩余10条评论
3个回答

1
很高兴地报告,我花了10个小时才发现最后登录时设置的cookie是"jwt",而我在中间件中一直在寻找名为"token"的cookie。

1

删除此内容或将其设为假, 凭据:真

后端和前端都要考虑


1
我不太确定,但可能与设置安全的cookie有关。
setCookie("id", res._id, {
                path: "/",
                sameSite: "none",
                secure: true,
          });

在这种情况下,您不应该将*设为允许的来源。我认为配置 CORS 可能会解决这个问题。

allowedOrigin.js:

const allowedOrigins = ["your-frontend-app-port"];

module.exports = allowedOrigins;

corsOptions.js:

const allowedOrigins = require("./allowedOrigins");

const corsOptions = {
  origin: (origin, callback) => {
    if (allowedOrigins.indexOf(origin) !== -1 || !origin) {
      callback(null, true);
    } else {
      callback(new Error("Not allowed by CORS"));
    }
  },
  optionsSuccessStatus: 200,
};

module.exports = corsOptions;


在index/server.js文件中
app.use(cors(corsOptions));

不确定。只是一种直觉。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接