我在我的网站中使用了几种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-http和passport-anonymous以及其他几个,但我不确定应该使用哪个。
为用户创建数据库条目对我很重要。所以稍后我可以附加另一个帐户。
答案 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);
});
});