NodeJS Passport

24

我在Node.js上设置了护照(Passport),并使用Mongoose使其能够允许用户登录和创建新账户。

app.js:

var express = require('express')
  , app = module.exports = express.createServer()
  , passport = require('passport')
  , LocalStrategy = require('passport-local').Strategy
  , routes = require('./routes/index')(app) //index loads in multiple routes
  , MongoDBConnection = require('./database/DatabaseConnector').MongoDBConnection;

// Configuration
app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.cookieParser());
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.session({ secret: 'justdoit' }));
  app.use(passport.initialize());
  app.use(passport.session());
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});

var mongoDbConnection = new MongoDBConnection();

passport.serializeUser(function(user, done) {
    done(null, user.id);
});

passport.deserializeUser(function(id, done) {
    mongoDbConnection.findUserById(id, function(err, user){
       done(err, user);
    });
});

passport.use(new LocalStrategy(
    function(username, password, done) {
        process.nextTick(function () {
            mongoDbConnection.findUser(username, function(err, user) {
                //conditions....
            });
        });
    }
));

app.get('/', function(req, res){
    res.render('index', { title: "Index", user: req.user });
});

app.get('/account', ensureAuthenticated, function(req, res){
    res.render('account', { title: "Account", user: req.user });
});

app.get('/login', function(req, res){
    res.render('login', { title: "Login", user: req.user, message: req.flash('error') });
});

app.post('/login',
    passport.authenticate('local', {
        successRedirect: '/account',
        failureRedirect: '/login',
        failureFlash: true })
);

function ensureAuthenticated(req, res, next) {
    if (req.isAuthenticated()) { return next(); }
    res.redirect('/login')
}

我的问题是app.js文件(其中包含passport代码)太大了,我尝试将passport部分移动到它自己的脚本中,并将路由放在app.js之外并放在自己的auth.js路由文件中,然后通过app.js引用该路由。它可以适用于其他路由,但对于与passport相关的路由(例如登录),似乎不会触发passport.authenticate()函数。

有没有办法将passport路由和函数放入自己的文件中,并从app.js进行调用/加载?

auth.js:

module.exports = function(app){

passport.serializeUser(function(user, done) {
    done(null, user.id);
});

passport.deserializeUser(function(id, done) {
    mongoDbConnection.findUserById(id, function(err, user){
        done(err, user);
    });

});

passport.use(new LocalStrategy(
    function(username, password, done) {
        process.nextTick(function () {

            mongoDbConnection.findUser(username, function(err, user) {

                if (err) {
                    return done(err);
                }
                if (!user) {
                    return done(null, false, { message: 'Unknown user ' + username });
                }

                if (user.password != password) {
                    return done(null, false, { message: 'Invalid password' });
                }

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

app.get('/', function(req, res){
    res.render('index', { title: "Index", user: req.user });
});

app.get('/account', ensureAuthenticated, function(req, res){
    console.log("directing to the account page....");
    res.render('account', { title: "Account", user: req.user });
});

app.get('/login', function(req, res){
    res.render('login', { title: "Login", user: req.user, message: req.flash('error') });
});

app.post('/login',
    passport.authenticate('local', {
        successRedirect: '/account',
        failureRedirect: '/login',
        failureFlash: true })
);

function ensureAuthenticated(req, res, next) {
    if (req.isAuthenticated()) { return next(); }
    res.redirect('/login')
}
}

添加了一些代码。基本上,我想将其转移到外部路由文件中,并从app.js中移除混乱代码。 - DanyZift
你能同时发布app.js v2吗?可能的问题是模块无法看到你在app.js中创建的passport对象。你传递了app,但没有传递passport。尝试:module.exports = function(app, passport){... - UpTheCreek
app.js 2与上面的代码相同,只是去掉了passport函数。我仍然包括passport = require('passport')和用于session的app.use函数。我已经尝试过传递passport对象,但也没有起作用。我以为在app.js中配置passport时,它会在全局范围内。 - DanyZift
5个回答

39

这是我的做法。如果需要更多帮助来适应您的代码,请留言评论。

第一步

将您的护照代码放入单独的文件中,例如pass.js。(我看到您已经这样做了)然后,在那个文件中,将所有代码放在这个语句中:

module.exports = function(passport, LocalStrategy){

};

记得在函数输入中添加任何其他你正在使用的内容。对于你的情况,除了passport和LocalStrategy,你可能还需要将mongoDbConnection作为一个输入加入。

第二步

在你的app.js中,包含这行代码。如果可能的话,在"app.listen"之前以确保一切都已被正确定义/声明/包含。

require('./pass.js')(passport, LocalStrategy);

解释

步骤一中的"wrapper"定义了你将要包含到应用程序中的代码块。步骤二中的"require"是实际包含它的代码。你基本上将整个"pass.js"文件定义为一个函数,并传递给它执行代码所需的工具(passport,LocalStrategy等)。

在你的情况下,你可能需要修改我的代码:

module.exports = function(passport, LocalStrategy, mongoDbConnection){

};

require('./pass.js')(passport, LocalStrategy, mongoDbConnection);

这应该是有效的。我之前也查过谷歌,这似乎是拆分您的app.js文件的“正确”方法(虽然我说这话还是有点紧张 :))。如果需要更多帮助,请随时评论。


@DanyZift:非常高兴知道它有所帮助! - Legendre
@Legendre 天才!感谢! - shaunakde

6

4
我建议在app.js中执行以下操作。
 require('./mypassport')(app);

并且mypassport.js

var passport = require('passport')
, LocalStrategy = require('passport-local').Strategy

, MongoDBConnection = require('./database/DatabaseConnector').MongoDBConnection;

  module.exports = function(app){

    passport.serializeUser(function(user, done) {
     done(null, user.id);
   });

  passport.deserializeUser(function(id, done) {
   mongoDbConnection.findUserById(id, function(err, user){
    done(err, user);
  });

});

passport.use(new LocalStrategy(
function(username, password, done) {
    process.nextTick(function () {

        mongoDbConnection.findUser(username, function(err, user) {

            if (err) {
                return done(err);
            }
            if (!user) {
                return done(null, false, { message: 'Unknown user ' + username });
            }

            if (user.password != password) {
                return done(null, false, { message: 'Invalid password' });
            }

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

1

在Legendre的回答基础上,module.exports = function()是在nodejs中将文件、变量或某些功能全局可用于整个应用程序的一种方式。

// anyfile.js
  module.exports = function(){ 
    //global code.
}

0
module.exports = function(app){

passport.serializeUser(function(user, done) {
    done(null, user.id);
});

可能是因为您没有对护照对象进行引用,所以它无法正常工作?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接