passport的驗證過程主要依賴具體的驗證策略來實現的,比較經常使用的有session策略、local策略和github策略等,驗證邏輯都是在這些策略類中定義的。passport模塊的定義主要包括三個部分:passport類、相關中間件和驗證策略,passport自帶了session驗證策略,若是要使用其餘驗證策略,須要自行添加。git
passport的使用分爲五個部分:github
app.use(passport.initialize())
對passport進行初始化,不然後面的驗證方法沒法執行app.use(passport.session());
,這個主要是爲了記住用戶的登陸狀態,能夠指定session過時時間本文沒有對passport進行深刻的分析,具體請參考註釋版源碼。express
依賴於 ./framework/connect
和 ./strategies/session
主要屬性:session
this._key = 'passport'; //掛載在session上的關鍵字 this._strategies = {}; //保存全部驗證策略的對象 this._serializers = []; //序列化session this._deserializers = []; //反序列化session this._infoTransformers = []; this._framework = null; //保存全部中間件的對象 this._userProperty = 'user'; //掛載在req上的關鍵字 req.user
進行相關初始化,添加authenticate和initialize中間件,添加session驗證策略 。給req對象添加login、logout、isAuthenticated和isUnAuthenticated方法app
passport暴露的中間件是相似於connect風格的,簽名如:fn(req, res, next)
,而有的框架須要的是不一樣的簽名風格,所以,該方法是用來作適配的,若是使用的是express框架,則不須要調用該方法。將傳入的參數保存到this._framework中,參數以下:框架
{ initialize: initialize, authenticate: authenticate }
添加具體驗證策略對象,並保存到this._strategies中,策略對象必須提供名稱,例如:
passport.use('local',new LocalStrategy(function(username,password,done){ //todo });
函數
根據策略名稱,刪除this._strategies中對應的驗證策略對象,例如:passport.unuse('local');
this
設置this._userProperty,而後調用this._framework.initialize方法生成一個初始化中間件,並返回該中間件prototype
調用this._framework.authenticate方法生成一個驗證中間件,並返回該中間件code
主要包括initialize和authenticate,除此以外,在加載的時候還會對req對象定義多個方法
進行相關初始化工做,將session中的passport對象(req.session[passport._key])掛載到req._passport上,若是session中沒有保存相關信息或者session爲空,則req_passport={}
給驗證策略添加了額外的處理方法,如:success、fail、redirect、pass、error,主要目的是對驗證狀態進行保存。有了這些方法,咱們就能夠只關心驗證邏輯的定義,在驗證成功或失敗後只需調用這些預先定好的方法便可。該中間件對請求按照指定的策略進行驗證,若是驗證經過,調用success方法,用戶就會登陸成功,相關用戶信息將被掛載到req.user上同時會生成一個session對象,若是驗證失敗,將會向客戶端發送未受權響應。
該中間件須要注意的地方就是驗證回調,若是提供了回調函數,那麼將會覆蓋默認的處理方式,即:attemp方法,此時須要自行調用req.login
//提供了回調函數的狀況 app.get('/login', function(req, res, next) { passport.authenticate('local', function(err, user, info) { if (err) { return next(err); } if (!user) { return res.redirect('/login'); } req.logIn(user, function(err) { if (err) { return next(err); } return res.redirect('/users/' + user.username); }); })(req, res, next); });