2012-10-16 96 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