Node.js Multer前后认证中间件

Node.js Multer前后认证中间件,node.js,express,multer,Node.js,Express,Multer,我正在使用express创建一个API 我以多部分形式接收数据。我想上传一个图像,但只有在用户通过身份验证之后 这是我为验证用户而创建的中间件: const jwt = require('jsonwebtoken'); const pool = require('../utils/connectionPool'); function authorizeUser(req, res, next){ try{ const authHeader = req.headers.

我正在使用express创建一个API

我以多部分形式接收数据。我想上传一个图像,但只有在用户通过身份验证之后

这是我为验证用户而创建的中间件:

const jwt = require('jsonwebtoken');
const pool = require('../utils/connectionPool');

function authorizeUser(req, res, next){

    try{

        const authHeader = req.headers.authorization;
        const token = authHeader && authHeader.split(' ')[1];
        if(token==null) return res.json({
            status: 000,
            msg: "Token Missing"
        });

        //TODO: Change secret.
        jwt.verify(token, 'mysecret', async (err, user)=>{

            if(err){
                // console.log(err);
                res.json({
                    status: 001,
                    msg: "Invalid Token."
                });
                return;
            }

            if(req.body.id == undefined || req.body.id != user.id){

                res.json({
                    status: 002,
                    msg: "User not authenticated."
                });
                return;

            }

            let login_timestamp = user.login_timestamp;
            
            //Check login token in db.
            let checkToken = await pool.query(`SELECT status FROM user WHERE id=? AND login_timestamp=?`, [user.id, login_timestamp]);

            if(checkToken.length > 0){

                if(checkToken[0].status == 0){
                    res.json({
                        status: 004,
                        msg: "Auth failed. Account Disabled."
                    });
                    return;
                }

                next();
            }else{
                res.json({
                    status: 003,
                    msg: "Timestamp does not match."
                });
                return;
            }
        });
    }catch(e){
        // console.log(e);
        res.json({
            status: 005,
            msg: "User auth failed. Internal Server Error."
        });
        return;
    }
}
所以要访问req.body,首先需要使用multer.single(“image”)作为中间件

现在,如果我在使用authorizeUser之前使用multer.single(“image”),那么即使在检查用户的身份之前,图像也会首先上传。如果我在authorizeUser之后使用它,那么我无法访问authorizeUser中的req.body。如果我使用以下顺序的中间件:multer.none(),authorizeUser,multer.single(“图像”),那么它不会上传图像

如何解决这个问题?在访问authorizeUser中的req.body时,如何首先授权用户,然后上载图像

下面是我要解析多种形式数据的代码:

const express = require('express')
const bodyparser = require('body-parser');
const pool = require('./utils/connectionPool')
const multer = require('multer');

const app = express()
app.use(bodyparser.json());
app.use(express.urlencoded({extended: true}))
const port = 3000

// @beyondhelloworld by Femin Dharamshi

const login = require('./routes/login');
const {authorizeUser} = require('./utils/auth');

var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, 'uploads/')
  },
  filename: function (req, file, cb) {
    cb(null, Date.now() + file.originalname)
  }
})

var upload = multer({ storage: storage })

app.get('/', upload.single('image'), authorizeUser, async (req, res) => {

  //This is just for trial.
  resp = await pool.query("SELECT * FROM user WHERE id=?",[req.body.id]);
  res.json(resp)
})

app.use('/login', login);

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

编辑:TL;DR我想在文件上传之前访问req.body。

修改代码如下

uploadRouter.post('/path',fileuploadFunction)

const fileuploadFunction = async (req,res) => {

   // Here you should be able to read your body
      await authorizeUser(req.body.id)

   // Upload file
      await uploadFile(req,res)  

}

const uploadFile = util.promisify(multer({ storage: yourStorage, limits, fileFilter }).single('file'))

这就是在授权后使用multer上载图像的方式

如果没有前端来测试文件上传,则需要使用所需的API模拟请求。我正在使用这个例子

首先,在邮递员中设置您的请求。 您必须对要测试的端点使用
POST
请求

这是一张照片:

注意在body选项卡中,您必须使用
表单数据
,为
(我使用了图像)输入一个值,并在该值旁边的下拉菜单(左侧)中,使用
文件
。现在你可以上传你的图片了

第二,你的代码…(注意我已经为这个测试删除了很多杂音和不必要的代码,但是你仍然能够解决问题):

现在,一旦您对代码进行了必要的调整,请单击“发送”,通过邮递员发送请求

由于变量
isauthorized
为false(模拟未授权用户的初始值),从邮递员GUI中可以看到,返回给用户的响应为:“用户未授权”

现在检查服务器日志;正如您所看到的,没有文件被打印到控制台

接下来,将变量isauthorized更改为
true
,并通过邮递员重新发送请求(您可能需要重新启动服务器…)

请参阅回复:“用户授权”

再次检查服务器日志,现在可以看到文件已加载,可用于进一步处理:

  {
    fieldname: 'image',
    originalname: 'myAvatar.png',
    encoding: '7bit',
    mimetype: 'image/png',
    buffer: <Buffer 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 00 c8 00 00 00 c8 08 06 00 00 00 ad 58 ae 9e 00 00 20 00 49 44 41 54 78 9c ec 9d 77 5c 14 e7 d6 ... 27133 more bytes>,
    size: 27183
   }
{
字段名:“图像”,
原始名称:“myAvatar.png”,
编码:“7bit”,
mimetype:'image/png',
缓冲区:,
尺码:27183
}

这有帮助吗?

我尝试过,但在将请求发送到multer之前,我无法访问req.body.id,因为表单数据是多部分表单数据,而不是普通的JSONC。请添加:1。您的前端代码仅显示用于上载文件和2的表单或任何其他机制。显示如何声明和实例化multer的代码。您的计算机中没有任何multer代码OQ@rags2riches前端正在使用Flatter移动应用程序,首先我有一个疑问,数据不包含任何文件,我应该仍然使用multipart还是应该将数据作为json发送,只有当它包含任何文件时,我才应该使用multipart?请更新您的答案?我无法理解您的代码是如何运行的,因此如果我看到code@rags2riches好的,我更新了我的问题!非常感谢。您还需要添加前端代码。只要表格就足够了是的,这很有意义!非常感谢你!现在我只有一个疑问。验证后,映像位于req.file中,对吗?如何将此图像保存到目录中?您只需像在代码中一样使用
multer存储对象
,但使用正斜杠,例如/directory
  {
    fieldname: 'image',
    originalname: 'myAvatar.png',
    encoding: '7bit',
    mimetype: 'image/png',
    buffer: <Buffer 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 00 c8 00 00 00 c8 08 06 00 00 00 ad 58 ae 9e 00 00 20 00 49 44 41 54 78 9c ec 9d 77 5c 14 e7 d6 ... 27133 more bytes>,
    size: 27183
   }