使用哪种护照认证

时间:2012-10-16 16:22:26

标签: node.js passport.js

我在我的网站中使用了几种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
        });
      });
    }
  });
});

用户架构如下所示:

UserSchema = new Schema({
  uname: {type: String},
  accounts: [],
  docs:[{type:Schema.Types.ObjectId, ref:'Doc'}]
})

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

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

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

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

3 个答案:

答案 0 :(得分: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代码。

答案 1 :(得分: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);
          });
        }
      });
    }
  }
));

可能它充满了错误,并且错误处理不完整,但似乎是正确的解决方案,它已集成到备受赞赏的passport库中,

答案 2 :(得分: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);
  });
});