首页 > 解决方案 > 如何在 CORS 中间件中读取自定义标头

问题描述

我使用CORS包创建了 CORS 中间件。这个中间件将在每次调用之前被调用。这是我的实现。

const corsMiddleware = async (req, callback) => {
  const { userid } = req.headers|| req.cookies {};
  let whiteList = await getWhiteListDomains(userid)
  return callback(null, {
    origin: whiteList,
    credentials: true,
    allowedHeaders: ["userid", "authorization", "content-type"]
  });
};

并在路由初始化之前添加了这个中间件

app.use(cors(corsMiddleware));
app.options("*", cors(corsMiddleware));



app.get("/user", (req, res, next)=>{
    // code
})

从浏览器中,我尝试将 API 调用为

axios({ method: "get", url: "http://localhost:3000/user", headers: {userId:"1234"} });

在我看到的服务器上调试时

access-control-request-headers:"userid"

在请求对象的标头中。

我无法读取自定义标题。这可能是因为我试图在 CORS 初始化之前读取自定义标头。但是,我仍然想阅读那个自定义标题。

标签: javascriptnode.jsexpresscors

解决方案


您的代码主要有两个问题。

第一个,更容易解决的是,您access-control-allow-origin在设置的选项中缺少Access-Control-Allow-Headers

return callback(null, {
  origin: whiteList,
  credentials: true,
  allowedHeaders: [
    "access-control-allow-origin",
    "authorization",
    "content-type",
    "userid"
  ]
});

第二个是最重要的,因为它与 CORS 的工作方式有关。您遇到的这个问题是 CORS 已经在飞行前OPTIONS请求中拒绝了请愿书。它从不允许浏览器执行GET请求。

您说您想userId在飞行前OPTIONS请求中读取自定义标头,但您不能。原因是飞行前OPTIONS请求是由浏览器自动创建的,它不会使用您在 Axios 调用中设置的自定义标头。它只会为 CORS发送这些标头:

Origin // URL that makes the request
Access-Control-Request-Method // Method of the request is going to be executed 
Access-Control-Request-Headers // Headers allowed in the request to be executed

因为您的自定义标头没有在飞行前发送,所以OPTIONS当您尝试访问 的值时userId,您会得到一个undefined值:

const { userid } = req.headers|| req.cookies;
console.log(userid); // undefined

而且由于您使用的值在异步函数中不匹配,因此getWhiteListDomains可能会得到另一个值,因此在 CORS 中间件选项中undefined设置的值会导致 CORS 中间件拒绝飞行前请求。originundefinedOPTIONS

let whiteList = await getWhiteListDomains(userid); // userid === undefined
console.log(whitelist); // undefined
return callback(null, {
  origin: whiteList, // undefined
  credentials: true,
  allowedHeaders: ["userid", "authorization", "content-type"]
});

我不完全确定您尝试使用自定义标头作为 CORS 检查的目标是什么,但我的建议是在处理自定义 CORS 配置时只检查Origin标头,因为这是它的目的:限制和控制哪些 URL 可以访问您的服务器和资源

如果您有兴趣在服务器收到的请求中创建任何类型的授权或受用户实现的限制,我建议您使用不同的自定义中间件,并且像现在尝试的那样完全不涉及 CORS。


推荐阅读