由于自定义 header 缺失,身份验证中间件阻止了 OPTIONS 预检请求

Authentication middleware blocks OPTIONS preflight request due to custom header absence

我有一个使用 axios 作为 HTTP 库的 React 应用程序,express 服务器使用 http-proxy-middleware 包和 API express 服务器包含 APIs.

React 应用程序应该像这样通过代理身份验证服务器与 API 服务器通信:

在我的 React 应用程序中,我创建了这个测试方法:

testReq(){
    axios.get('http://localhost:5000/applicationData/checkMe', {
      withCredentials: true,
      headers: {
        'x-access-token': '...'
      }
    })
    .then(response => console.log(response.status))
    .catch(e => console.log(e))
  }

这是我的代理方法的样子:

server.use('/applicationData', authenticate, proxy({
    target: 'http://localhost:4000',
    changeOrigin: false,
    onProxyReq(proxyReq, req) {
      // proxyReq.setHeader('x-access-identity-email', req.decodedToken.email)
    },
  }))

这是上面用到的authenticate中间件函数:

module.exports = (req, res, next) => {
  const token = req.headers['x-access-token']
  console.log('token', token)
  if (token) {
    verifyToken(token, global.config.secret).then((verificationResponse) => {
      const { decoded, message } = verificationResponse
      if (!decoded) return res.status(401).json({ message })
      req.decoded = decoded
      return next()
    })
    .catch((err) => {
      console.error(err)
      res.status(500).json({ message: 'Internal error' })
    })
  } else return res.status(401).json({ message: 'Missing authentication token' })
}

我在 API 和代理服务器上启用了 CORS,如下所示:

server.all('/*', (req, res, next) => {
    res.header('Access-Control-Allow-Origin', 'http://localhost:3000')
    res.header('Access-Control-Allow-Headers', 'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept, x-access-token')
    res.header('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS')
    res.header('Access-Control-Allow-Credentials', 'true')
    next()
  })

问题是我在发送请求时收到此响应:

我认为这是由于身份验证中间件试图从不存在的 OPTIONS 请求访问 x-access-token header,因此 returns 401。如果我删除 authentication 来自代理方法的中间件然后请求通过。

如何让 x-access-token 出现在 OPTIONS 请求中?否则,处理这种情况的正确方法是什么?

在 facebook 中不允许粘贴代码不确定,为什么,所以粘贴在这里:

在您的中间件中缺少的是(对于您评论的选项部分):

if (req.method == 'OPTIONS') {
  res.send(200);
}
else {
  next();
}

对于错误部分,正如您所说的在 cors 部分之前触发身份验证,因此您可能必须在身份验证之前设置该代码(安全部分我不太确定)

我认为行:

    res.header('Access-Control-Allow-Headers', 'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept, x-access-token')

应该是:

    res.header('Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept, x-access-token')