Node.js 使用哪种护照身份验证

Node.js 使用哪种护照身份验证,node.js,passport.js,Node.js,Passport.js,我在我的网站上使用了几种Passport身份验证策略,效果很好,但是,我需要一种Demo或(我们可以称之为session)策略,它根据用户的会话id自动授权用户,现在我正在手动执行,当用户导航到/Demo页面时,我在db(mongodb)上运行一个查询,使用会话id,如果用户存在,我将使用该用户呈现页面,如果不存在,我将创建一个 app.get('/demo', function(req,res) { db.User.findOne({ 'accounts.kind': 'demo', 'a

我在我的网站上使用了几种Passport身份验证策略,效果很好,但是,我需要一种
Demo
或(我们可以称之为
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策略之一。我看到有,和,还有其他几个,但我不确定我应该用哪一个


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

请从中查看第4节。这是将会话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);
  });
});

我可以这样解决: 确定了新的战略,

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(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);
          });
        }
      });
    }
  }
));

也许它充满了bug,错误处理还没有完成,但似乎是正确的解决方案,它集成到了备受赞赏的库中,

事实证明,在这种情况下,创建自定义策略是不必要的。我发现该官员有一个(未记录的)
passReqToCallback
选项,允许您在verify函数中访问
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个参数
req、username、password、done
,从
req
对象开始,而不是默认的3个参数


我希望这能为您节省一些时间,在阅读LocalStrategy代码之前,我花了一个小时试图解决这个问题。

这对cookie不起作用吗?@Patrick是的,它涉及cookie,会话id在cookie中,那么您就不需要策略了。序列化和反序列化应该会自动工作,并在用户返回时检索会话。我有这些函数,但它们是由passport.session()中间件调用的(如果我是对的),当我使用演示身份验证时,passport会被完全跳过。按设计:)最后我创建了一个新策略,请参见下面(或上面)的Hmm,好的。对不起,我没听清楚。不,不,对我问题的描述很弱。感谢您的时间,我还是从您的回答中学到了一些东西。请注意:其他策略也有此选项。我已经在使用LocalStrategy,我认为它不能被使用两次。实际上,您可以多次使用它,您只需在passport配置中为它命名,如:
passport.use('other-login',new LocalStrategy())app.post('/otherlogin',passport.authenticate('other-login')。没有名字,LocalStrategy的默认名称为“local”,这真的是使用会话信息对用户进行身份验证的最佳方式,这样他们就不必重新输入用户名/密码吗?在我的例子中,这是一个临时用户(尝试演示用户),可以转换为完全注册的用户。我使用了许多passport身份验证策略,因此它非常适合我的应用程序。