NodeJS ExpressJS PassportJS - 仅用于管理页面

Posted

技术标签:

【中文标题】NodeJS ExpressJS PassportJS - 仅用于管理页面【英文标题】:NodeJS ExpressJS PassportJS - for Admin Pages Only 【发布时间】:2013-06-16 21:18:12 【问题描述】:

我正在使用 NodeJS、ExpressJS、Mongoose、passportJS 和 connect-ensure-login。对用户进行身份验证非常有效。

....
var passport = require('passport')
  , LocalStrategy = require('passport-local').Strategy
  , ensureLoggedIn = require('connect-ensure-login').ensureLoggedIn;

var app = express();
...
app.use(passport.initialize());
app.use(passport.session());    
...


passport.use(new LocalStrategy(usernameField: 'email', passwordField: 'password',
    function(email, password, done) 
  User.findOne( 'email': email, 'password': password ,
               '_id': 1, 'email':1, function(err, user) 

    if (err)  return done(err); 

    if (!user) 
      return done(null, false,  message: 'Incorrect username.' );
    

    return done(null, user);
  );
));

passport.serializeUser(function(user, done) 
  done(null, user);
);

passport.deserializeUser(function(user, done)   
  done(null, user);
);

app.post('/login', passport.authenticate('local',
     successReturnToOrRedirect: '/home', failureRedirect: '/login' ));

app.get('/logout', function(req, res)
  req.logout();
  res.redirect('/');
);

现在,我想对某些路线添加限制,以便只有管理员才能访问。我怎样才能做到这一点?例如/admin/*

var schema = new mongoose.Schema(
    name: String,
    email: String,
    password: String,
    isAdmin:  type: Boolean, default: false 
);

mongoose.model('User', schema);

有什么提示吗?谢谢

【问题讨论】:

【参考方案1】:

您可以将自定义中间件附加到 /admin/* 路由,该中间件将在任何更具体的 /admin/ 路由上传递请求之前检查管理员状态:

var ensureLoggedIn = require('connect-ensure-login').ensureLoggedIn;
...
var requiresAdmin = function() 
  return [
    ensureLoggedIn('/login'),
    function(req, res, next) 
      if (req.user && req.user.isAdmin === true)
        next();
      else
        res.send(401, 'Unauthorized');
    
  ]
;

app.all('/admin/*', requiresAdmin());
app.get('/admin/', ...);

【讨论】:

我添加了你的解决方案,但我想我错过了一些东西,它总是未经授权。 @JRGalia 你说得很对,我编辑了我的答案来修复这个错误:) @robertklep 如果我们只需要对管理员用户进行身份验证,这个解决方案就可以工作,如果我们想同时从管理员和用户登录怎么办,req.user 将已经有管理员用户。当我们将尝试与普通用户进行身份验证时,我们该如何处理。有没有办法在验证管理员用户后设置 req.admin 并在验证普通用户后设置 req.user @HamzaKhan 作为管理员通常是可以分配给任何用户的属性,这也是此代码所依赖的(isAdmin 存储在数据库中,并设置为true对于任何具有管理员权限的用户)。 Passport 不支持多个同时登录的用户。如果您的意思是希望能够在同一浏览器中以普通用户和管理员身份登录,请考虑为一个用户使用隐身/隐私浏览模式,为另一用户使用常规浏览模式。 @robertklep 感谢您的回答,这正是我想知道的。我现在使用 req.session.user 和 req.session.admin 来保持两种类型的用户同时登录,请告诉我这是一种不好的方法,或者我们可以接受。【参考方案2】:
//Add following function to your app.js above **app.use(app.router)** call;

//This function will be called every time when the server receive request.

app.use(function (req, res, next) 
  if (req.isAuthenticated || req.isAuthenticated())
  
    var currentUrl = req.originalUrl || req.url;
    //Check wheather req.user has access to the above URL
    //If req.user don't have access then redirect the user
    // to home page or login page
    res.redirect('HOME PAGE URL');
  
  next();
);

我没有尝试过,但我认为它会起作用。

【讨论】:

应该是if (req.isAuthenticated())

以上是关于NodeJS ExpressJS PassportJS - 仅用于管理页面的主要内容,如果未能解决你的问题,请参考以下文章

NodeJs + ExpressJs 应用程序路由奇怪的行为

req.session.passport 为空,未调用 deserializeUser - ExpressJS,Passport

ExpressJS - JWT 和 Passport 实现

使用 Passport 和 ExpressJS 进行 Facebook 身份验证 - 为啥不调用验证回调?

尝试获取资源 Passport ReactJS 和 ExpressJS 时出现 NetworkError:CORS

带有passport.js的微服务认证架构