如何使用 Passport 本地身份验证为 Node.js 应用程序的 Axios 请求形成身份验证 Header?

How to Form Authentication Header for Axios Request to Node.js App Using Passport Local Authentication?

我有一个 node.js 应用程序,正在开发一个单独的单页应用程序(最终将转换为 Android 和 iOS 本机应用程序)。我正在 node.js 应用程序上设置 API 并且正在努力进行身份验证。 node.js 应用程序使用 passport-local-mongoose 进行身份验证,我将用户数据存储在 MongoDB 后端。对于 testing/dev,单页应用在 http://localhost:1234/ 上是 运行。

我的端点看起来像:

exports.getDevicesAPI = async (req, res) => {
  res.header('Access-Control-Allow-Origin', req.headers.origin);
  res.header('Access-Control-Allow-Methods', 'GET, POST');
  res.header('Access-Control-Allow-Headers: Authorization');
  const devices = await Device.find({ owner: req.user._id });
  res.json(devices);
};

我可以 GET 这没问题,比如:

const axios = require('axios');
const url = 'http://localhost:7777/api/devices';

function getDevices() {
  axios
    .get(url)
    .then(function(response) {
      console.log(response);
    })
    .catch(function(error) {
      console.log(error);
    });
}

我想在服务器端添加authenticate = passport.authenticate('header', {session: false, failWithError: true});来提供身份验证,但是下面给了我Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:7777/api/devices. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing)

const axios = require('axios');    
const url = 'http://localhost:7777/api/devices';

const username = myUsername;
const password = myPassword;

const axiosConfig = {
  headers: {
    'Content-Type': 'application/json',
  },
  Authorization: {
    username,
    password,
  },
};

function authenticate() {
  axios
    .post(url, axiosConfig)
    .then(function(response) {
      console.log('Authenticated');
    })
    .catch(function(error) {
      console.log('Error on Authentication');
    });
}

路线(用于测试):

router.get('/api/devices', catchErrors(deviceController.getDevicesAPI));
router.post('/api/devices', catchErrors(deviceController.getDevicesAPI));

我错过了什么?

您遇到了 CORS(Cross-Origin 资源共享)限制的问题。阅读有关 CORS 的更多信息 here

我相信您的这部分代码旨在处理 CORS:

exports.getDevicesAPI = async (req, res) => {
  // ...
  res.header('Access-Control-Allow-Origin', req.headers.origin);
  res.header('Access-Control-Allow-Methods', 'GET, POST');
  res.header('Access-Control-Allow-Headers: Authorization');
  // ...
};

然而,这里的错误是这些 CORS headers 的设置与路由相关联,即不应该是 getDevicesAPI 路由。对于可能修改另一个来源的资源的请求(例如 POST 到 getDevicesAPI 路由),浏览器将在发送实际请求之前首先使用 OPTIONS Http 方法发送预检请求,对预检请求的响应是预期设置必要的 CORS response-headers 的地方。您可以找到有关预检请求的解释 here

我通常会在其他路由之上添加这样的中间件:

router.all('*', (req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
  res.header('Access-Control-Allow-Headers', '*');
  next();
});