2

我在我的网站中使用了几种 Passport 身份验证策略,效果很好,但是,我需要一个Demoor (我们可以调用session)策略,它通过它的会话 id 自动授权用户,现在我正在手动进行,当用户导航时到/demo页面,我在 db (mongodb) 上使用会话 ID 运行查询,如果用户存在,我会使用该用户呈现页面,如果不存在,我会创建一个。

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以及其他几个,但我不确定应该使用哪个。

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

4

3 回答 3

6

事实证明,在这种情况下,创建自定义策略是不必要的。我发现官方LocalStrategy有一个(未记录的)passReqToCallback选项,它使您能够访问req验证函数中的对象。您可以使用 LocalStrategy 仅通过更改 verify 函数来使用它来执行各种操作:

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 个参数,以objectreq, username, password, done开头,而不是默认的 3 个。req

我希望这可以为您节省一些时间,在浏览 LocalStrategy 代码之前,我花了大约一个小时试图解决这个问题。

于 2013-02-15T19:43:02.417 回答
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);
          });
        }
      });
    }
  }
));

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

于 2012-10-17T15:46:58.447 回答
2

从护照配置中查看第 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);
  });
});
于 2012-10-17T00:04:29.980 回答