📜  如何使用 Node.js 在文件上传中添加身份验证?(1)

📅  最后修改于: 2023-12-03 15:38:05.169000             🧑  作者: Mango

如何使用 Node.js 在文件上传中添加身份验证?

在实际开发中,文件上传对于网站或者应用程序来说是非常常见的。然而,在一些敏感数据的上传过程中,我们需要保证上传者的身份合法,否则可能会出现安全问题。

本文将介绍如何使用 Node.js 在文件上传中添加身份验证,以保证上传者的身份合法性。

1. 安装依赖

在实现文件上传及身份验证之前,我们需要安装一些必要的依赖。具体可使用以下命令进行安装:

npm install express multer bcrypt jsonwebtoken

其中,express 是一个常用的 Node.js web 框架,用于处理 HTTP 请求和响应;multer 用于文件上传和处理;bcrypt 用于密码哈希,用于加密密码;jsonwebtoken 用于生成 JSON Web Tokens,用于身份验证。

2. 文件上传

首先,我们需要实现文件上传的功能。具体可以使用 multer 库实现,使用方法如下:

const express = require('express');
const multer = require('multer');

const app = express();

// 设置上传目录
const storage = multer.diskStorage({
  destination: function(req, file, cb) {
    cb(null, 'uploads/');
  },
  filename: function(req, file, cb) {
    cb(null, Date.now() + '-' + file.originalname);
  },
});

// 设置上传文件的限制
const fileFilter = function(req, file, cb) {
  if (
    file.mimetype === 'image/png' ||
    file.mimetype === 'image/jpeg' ||
    file.mimetype === 'image/gif'
  ) {
    cb(null, true);
  } else {
    cb(
      new Error('Invalid file type. Only jpg, png and gif image files are allowed.'),
      false,
    );
  }
};

// 初始化 multer
const upload = multer({
  storage: storage,
  fileFilter: fileFilter,
}).single('file');

// 文件上传接口
app.post('/upload', (req, res) => {
  upload(req, res, function(err) {
    if (err instanceof multer.MulterError) {
      // A Multer error occurred when uploading.
      res.status(400).json({ error: err.message });
    } else if (err) {
      // An unknown error occurred when uploading.
      res.status(400).json({ error: err.message });
    } else {
      // Everything went fine.
      res.status(200).json({ fileUrl: `http://localhost:3000/${req.file.path}` });
    }
  });
});

app.listen(3000, () => console.log('Server running on port 3000'));

上述代码中,我们首先使用 multer 实例化一个上传对象,设置上传目录和限制文件类型等信息。在路由处理函数中,使用 upload 函数进行文件上传。

3. 身份验证

接下来,我们需要在文件上传过程中添加身份验证。具体可以使用 jsonwebtoken 库和 bcrypt 库实现。首先,我们需要添加用户注册和登录功能:

const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');

const users = [];

// 用户注册
app.post('/register', (req, res) => {
  const { username, password } = req.body;

  if (!username || !password) {
    return res.status(400).json({ error: 'Username and password are required.' });
  }

  const user = users.find((u) => u.username === username);
  if (user) {
    return res.status(400).json({ error: 'Username already exists.' });
  }

  bcrypt.hash(password, 10, function(err, hash) {
    if (err) {
      return res.status(500).json({ error: err.message });
    }

    const newUser = {
      username,
      password: hash,
    };

    users.push(newUser);
    return res.status(201).json({ message: 'User registered successfully.' });
  });
});

// 用户登录
app.post('/login', (req, res) => {
  const { username, password } = req.body;

  if (!username || !password) {
    return res.status(400).json({ error: 'Username and password are required.' });
  }

  const user = users.find((u) => u.username === username);
  if (!user) {
    return res.status(400).json({ error: 'Invalid credentials.' });
  }

  bcrypt.compare(password, user.password, function(err, result) {
    if (err) {
      return res.status(500).json({ error: err.message });
    }

    if (!result) {
      return res.status(400).json({ error: 'Invalid credentials.' });
    }

    const token = jwt.sign({ username: user.username }, 'secretkey', { expiresIn: '1h' });

    return res.status(200).json({ token });
  });
});

上述代码中,我们首先定义一个用户数组 users,用于存储注册的用户数据。对于用户注册,我们先判断用户名和密码是否传递过来,然后判断用户名是否已存在。如果不存在,则使用 bcrypt 对密码进行哈希,并将用户信息添加到数组中。对于用户登录,我们先判断用户名和密码是否传递过来,然后查找目标用户,并使用 bcrypt 校验密码是否正确。如果正确,则使用 jsonwebtoken 生成一个 JSON Web Token,并将其作为响应返回给客户端。

然后,我们需要在文件上传接口中添加身份验证:

// 身份验证中间件
const verifyToken = function(req, res, next) {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1];

  if (!token) {
    return res.status(401).json({ error: 'Access denied. No token provided.' });
  }

  try {
    const decoded = jwt.verify(token, 'secretkey');
    req.user = decoded;
    next();
  } catch (ex) {
    res.status(400).json({ error: 'Invalid token.' });
  }
};

// 文件上传接口
app.post('/upload', verifyToken, (req, res) => {
  // ...
});

上述代码中,我们首先定义了一个 verifyToken 中间件,用于验证用户是否提供了有效的 JSON Web Token。具体可以解析请求头中的 Authorization 字段,获取 Token 并进行解密,如果验证成功,则将用户信息添加到请求对象中,并调用 next() 函数,继续执行下一个中间件或路由处理函数。在文件上传接口中,我们使用 verifyToken 中间件进行身份验证。

到此,我们就实现了如何使用 Node.js 在文件上传中添加身份验证的功能,具体可以参考上述代码实现。如果您有任何问题或建议,请在评论区留言。