2013-10-24 293 views
6

過去幾天,我一直在使用Passport.js開發我的第一個用戶登錄&身份驗證系統。令人尷尬的是,我已經完成了它,它的工作原理與預期一樣。問題是,即使我已經閱讀了大量文章並在線查了幾十個例子,但我似乎並沒有完全理解代碼本身。我沒有理解它背後的過程,爲什麼它必須像那樣發生。如果你能爲我澄清代碼的某些部分,我將不勝感激。這是工作的代碼,保存在我的app.js文件:Passport.js用戶登錄和身份驗證

// Passport session setup 
passport.serializeUser(function (user, done) { 
    done(null, user._id); 
}); 

passport.deserializeUser(function (id, done) { 
    User.findById(id, function(err, user) { 
     done(err, user); 
    }); 
}); 

// Use the Local Strategy within passport 
passport.use(new LocalStrategy(function (username, password, done) { 
    User.findOne({ username: username }, function(err, user) { 
     if (err) { 
      return done(err); 
     } 

     if (!user) { 
      return done(null, false, { message: 'Unknown user: ' + username}); 
     } 

     user.comparePassword(password, function(err, isMatch) { 
      if (err) { 
       return done(err); 
      } 

      if (isMatch) { 
       return done(null, user); 
      } else { 
       return done(null, false, { message: 'Invalid Password' }); 
      } 
     }); 
    }); 
})); 

var app = module.exports = express(); 

app.configure(function() { 
    app.set('views', path.join(__dirname + '/views')); 
    app.set('view engine', 'html'); 
    app.engine('html', hbs.__express); 
    app.use(express.logger()); 
    app.use(express.cookieParser()); 
    app.use(express.bodyParser()); 
    app.use(express.methodOverride()); 
    app.use(express.session({ secret: 'xxx' }));  
    app.use(passport.initialize()); 
    app.use(passport.session()); 
    app.use(app.router); 
    app.use(express.static(path.join(__dirname + '/public'))); 

}); 

我使用MongoDB的(用戶 - 貓鼬模型)。此外,爲了將密碼存儲在數據庫中,我正在使用bcrypt。

我認爲這裏我不瞭解的最關鍵的部分是做的的回調函數。我可以理解它只是傳遞了一些值,我知道這很重要,它意識到第一個參數是錯誤,第二個參數是數據。不過,我並沒有完全理解它,因爲我沒有專門提供一個參數。例如,如果我將有這樣的功能:

// Random Function 
var randomFunction = function (a, b, done) { 
    done(a, b); 
}; 

// Then I would call the randomFunction providing my own **done** 
randomFunction('Random', 'Words', function(a, b) { return a + b; }); 

不過,在我的例子,我不是一個指定回調。這純粹是一個需要回調函數的參數還是一樣的下一個功能正常的中間件如:

function middleware (req, res, next) { 
    next(req.user); // pass the req.user to next middleware 
} 

而且,哪裏Passport.js其處理用戶綁定的?它是否綁定到請求用戶?我怎樣才能將它傳遞給某些視圖,例如,顯示用戶名?

我期待您的反饋!

謝謝!

回答

3

完成回調

看的Local Strategy代碼:

function Strategy(options, verify) { 
    ... 
    this._verify = verify; 
    ... 
} 

verify是將由策略被用來驗證用戶的功能,你已經在這裏指定它:

passport.use(new LocalStrategy(function (username, password, done) { 
    // your verification code here 
})); 

後來在策略中,您可以找到authenticate調用驗證函數的方法從上面的步驟:

this._verify(username, password, verified); 

所以,你現在看到usernamepassworddone==verified從何而來。稍後在您的代碼中,您將使用(err,user,info)參數調用done回調。簡而言之,需要done來完成用戶驗證的異步過程。

req.user和看法

是的,你說得對req.user。所以,你可以通過兩種方式將它傳遞給你的看法:

  1. 由於res.render函數的參數。 See docs

    res.render('some-template', { name: req.user }); 
    
  2. 使用res.locals爲某種上下文提供的(現在的用戶對象將在app.router中定義的所有視圖可用)。 See docs

    // before app.use(app.router); 
    app.use(function(req, res, next) { 
        res.locals.user = req.user; 
        next(); 
    }); 
    
+0

非常感謝您的反饋!據我所知,done是一個回調函數,用於從中間件返回信息。通過信息我的意思是3個參數(錯誤,用戶,信息)。基本上,我可以認爲完成的回調是(以高級方式)該特定中間件的回報? –

+1

如果我以正確的方式理解你的問題,沒有。 'done'只用於提供一些數據到下一個級別。您的驗證代碼將在調用'done()'後以正常方式執行,這就是爲什麼您應該使用'return done(err);'來停止執行您的驗證代碼。異步的東西是常見的情況。 –

+0

這就是我的意思^^我認爲我的回答有點含糊不清:)非常感謝您的反饋,我非常感謝! –