如何在Express.js中设置身份验证中间件

Ale*_*lex 6 authentication node.js express

我已经设置了一个Web应用程序,其中包含一些需要登录的内部页面.我使用Node和Express.js来设置服务器并控制路由和身份验证工作正常.

我在与同一应用程序相关问题中提出了@zanko建议,以避免在每个页面的路径中复制身份验证代码,就像现在一样.

目前我的app.js看起来像这样(以下是摘录):

var session = require('express-session');
//use sessions for tracking logins
app.use(session({
  secret: 'mercuia',
  resave: true,
  saveUninitialized: false,
  store: new MongoStore({
  mongooseConnection: db
})
}));

// serve static files from template
app.use(express.static(__dirname + '/public'));

// include routes
var routes = require('./routes/router');
app.use('/', routes);

// catch 404 and forward to error handler
app.use(function (req, res, next) {
  var err = new Error('File Not Found');
  err.status = 404;
  next(err);
});

// error handler
// define as the last app.use callback
app.use(function (err, req, res, next) {
  res.status(err.status || 500);
  res.send(err.message);
});
Run Code Online (Sandbox Code Playgroud)

虽然我的身份验证方法(在routes.js中)是(在示例中,对于route/clientPage):

// GET route after registering
router.get('/clientPage', function (req, res, next) {
  User.findById(req.session.userId)
    .exec(function (error, user) {
      if (error) {
        return next(error);
      } else {      
        if (user === null) {     
          var err = new Error('Not authorized! Go back!');
          err.status = 400;
          return next(err);
        } else {
          return res.sendFile(path.join(__dirname + '/../views/clientPage.html'));
        }
      }
    });
});
Run Code Online (Sandbox Code Playgroud)

我怎样才能编写一个认证中间件(使用相同的逻辑)并为所有人调用它而只需要请求路由?

You*_*neL 11

您可以创建一个名为的新模块auth.js,然后使用它来检查用户是否被授权:

auth.js

module.exports.isAuthorized  = function(req, res, next) {

    User.findById(req.session.userId).exec(function (error, user) {
        if (error) {
            return next(error);
        } else {      
            if (user === null) {     
                var err = new Error('Not authorized! Go back!');
                err.status = 400;
                return next(err);
            } else {
                return next();
            }
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

routes.js

var auth = require('./auth');

// GET route after registering
router.get('/clientPage', auth.isAuthorized, function (req, res, next) {
    res.sendFile(path.join(__dirname + '/../views/clientPage.html'));
});
Run Code Online (Sandbox Code Playgroud)

  • 真的很喜欢这个答案。我将err.status更改为401,因为这是授权问题。 (3认同)

Zan*_*nko 5

创建一个模块(一个导出函数的文件,在这种情况下为中间件函数)。中间件功能具有以下签名function (req, res, next) { .... }

strict.js

module.exports = function (req, res, next) {
  User.findById(req.session.userId)
    .exec(function (error, user) {
      if (error) {
        return next(error);
      } else {
        if (user === null) {
          const err = new Error("Not authorized! Go back!");
          err.status = 400;
          return next(err); // This will be caught by error handler
        } else {
          return next(); // No error proceed to next middleware
        }
      }
    });
};
Run Code Online (Sandbox Code Playgroud)

app.js

// serve static files from template
app.use(express.static(__dirname + '/public'));

// include routes
const routes = require('./routes/router');

//If you have a more granular route you can split it 
const someOtherRoute = require('./routes/someotherRoute');

const restrictMiddleware = require("./restrict");

app.use("/", someOtherRoute); // this route will not be check for authorization
app.use(restrictMiddleware);
app.use('/', routes);

// catch 404 and forward to error handler
app.use(function (req, res, next) {
  const err = new Error('File Not Found');
  err.status = 404;
  next(err);
});

// error handler
// define as the last app.use callback
app.use(function (err, req, res, next) {
  res.status(err.status || 500);
  res.send(err.message);
});
Run Code Online (Sandbox Code Playgroud)

我会用constlet,如果你的环境支持。它的2017年:)