2012-10-16 51 views
2

我在我的网站中使用了多种Passport认证策略,但效果很好,但是,我需要一个Demo或(我们可以拨打session)策略,通过它的会话ID自动授权用户,现在我当用户导航到/demo页面时,我使用会话ID在db(mongodb)上运行查询,并且如果用户存在,我使用该用户呈现页面,如果没有,我创建一个。使用哪种护照认证

app.get('/demo', function(req,res) { 
    db.User.findOne({ 'accounts.kind': 'demo', 'accounts.sid': req.sessionID }, function(err, user) { 
    if (user) { 
     res.render('home', { 
     user: user 
     }); 
    } else { 
     var user = new db.User(); 
     user.accounts.push({ 
     kind: 'demo', 
     sid: req.sessionID, 
     created: Date.now 
     }); 
     req.session.userId = user._id; 

     user.save(function(err) { 
     if(err) { throw err; } 
     res.render('home', { 
      user: user 
     }); 
     }); 
    } 
    }); 
}); 

用户的模式是这样的:

它的工作原理,但我需要设置一个会话变量,因为这种方法不登录的用户,我的意思是在没有req.user请求,但与该会话变量,我可以检查用户是否是演示用户。

if (req.user) { 
    userid = req.user._id.toString(); 
    } else { 
    userid = req.session.userId; 
    } 

我敢肯定有这样做,与现有护照策略的一个更优雅的方式。我看到有passport-httppassport-anonymous以及其他几个,但我不确定应该使用哪个。

对我来说,为用户创建数据库条目很重要。所以后来我可以附加一个另一个帐户。

+0

不适用于Cookie吗? – Patrick

+0

@Patrick是的,它涉及cookies,会话ID在cookie中, – balazs

+0

然后你不需要一个策略。序列化和反序列化应该自动工作,并在用户回来时检索会话。 – Patrick

回答

3

我可以解决这个问题是这样的: 定义了一个新战略,

var passport = require('passport') 
    , util = require('util'); 

function DemoStrategy(options, verify) { 
    if (typeof options == 'function') { 
    verify = options; 
    options = {}; 
    } 
    if (!verify) throw new Error('Demo Basic authentication strategy requires a verify function'); 

    passport.Strategy.call(this); 
    this.name = 'demo'; 
    this._verify = verify; 
} 

util.inherits(DemoStrategy, passport.Strategy); 

DemoStrategy.prototype.authenticate = function(req) { 
    var self = this; 
    this._verify(req, function(err, user) { 
    if (err) { return self.error(err); } 
    self.success(user); 
    }); 
} 

module.exports.Strategy = DemoStrategy; 

路线:

app.get('/auth/demo', 
    passport.authenticate('demo'), 
    function(req,res) { 
     res.redirect('/'); 
    } 
); 

和passport.use部分:

passport.use(new DemoStrategy( 
    function(req, done) { 
    console.log('using demo strategy, req: ', req); 
    if (req.user) { 
     // place code here, if we want to attach to an existing account 
    } else { 
     db.User.findOne({ 'accounts.kind': 'demo', 'accounts.sid': req.sessionID }, function(err, dbuser) { 
     if (dbuser) { 
      done(null,dbuser); 
     } else { 
      var user = new db.User(); 
      user.accounts.push({ 
      kind: 'demo', 
      sid: req.sessionID, 
      created: Date.now 
      }); 

      user.save(function(err) { 
      if(err) { throw err; } 
      done(null,user); 
      }); 
     } 
     }); 
    } 
    } 
)); 

也许它充满了错误,一个nd错误处理不完整,但似乎是正确的解决方案,它被集成到非常感谢的passport库中,

+1

这真的是使用会话信息验证用户的最佳方式,因此他们不必重新输入用户名/密码? –

+0

这是一个临时用户(尝试演示用户)在我的情况下,它可以变成一个完全注册的用户。我使用了许多护照认证策略,因此很适合我的应用。 – balazs

2

查看passport configuration的第4部分。这是将session-id放入cookie中并在用户返回时检索数据的代码。没有必要的战略。

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

passport.deserializeUser(function(id, done) { 
    User.findById(id, function (err, user) { 
    done(err, user); 
    }); 
}); 
+1

我有这些功能,但是这些是由passport.session()中间件(如果我是正确的)调用的,当我使用我的演示验证时,护照完全被跳过。 – balazs

+0

是故意还是意外? – Patrick

+1

由设计:)最后我创建了一个新的策略,见下面(或以上) – balazs

6

事实证明,在这种情况下创建自定义策略是不必要的。我发现官方LocalStrategy有一个(无证)passReqToCallback选项,它使您能够在验证功能中访问req对象。你只能通过改变校验功能用它做各种使用LocalStrategy东西:

passport.use(new LocalStrategy({ 
    passReqToCallback: true 
}, function(req, username, password, done) { 
    //now that you have req object, you can 
    //probably do whatever you need to do right here 
}); 

请记住,函数现在需要4个参数req, username, password, done,与req对象开始,而不是默认的3

我希望这可以节省一些时间,我花了一个小时试图在通过LocalStrategy代码之前解决此问题。

+0

只是一个说明:其他策略也有这个选项。我已经使用LocalStrategy,我不认为它可以使用两次。 – balazs

+0

你可以多次使用它,你只需要在护照配置中给它一个名字,例如: 'passport.use('other-login',new LocalStrategy());' 然后在路由中: 'app.post('/ otherlogin',passport.authenticate('other-login'));'。没有名字,LocalStrategy的默认名字是'local' – Joao