0

我正在學習javascript和node.js.如您所知,任何節點應用程序中最重要的部分之一是登錄模塊,因此我開始使用護照和本地護照,但我無法瞭解護照的身份驗證方式。我的護照認證過程的理解,下面是代碼:Express4和護照:無法驗證

'use strict'; 

var express = require('express'); 
var app = express(); 
var passport = require('passport'); 
var LocalStrategy = require('passport-local').Strategy; 
var dbConfig = require('./settings/db.js'); 
var mongoose = require('mongoose'); 
var expressSession = require('express-session'); 
var flash = require('connect-flash'); 

mongoose.connect(dbConfig.url); 

app.use(expressSession({ 
    secret: 'mySecretKey' 
})); 
app.use(passport.initialize()); 
app.use(passport.session()); 
app.use(flash()); 

var server = app.listen(3000, function() { 
    var host = server.address().address; 
    var port = server.address().port; 

    console.log('Admin app started at: %s %s ', host, port); 
}); 

passport.serializeUser(function(user, done) { 
    console.log('serializing user!'); 
    done(null, 'Hi'); 
}); 

passport.deserializeUser(function(id, done) { 
    console.log('deserializing user'); 
    done(null, { 
    '_id': 'Hi', 
    'username': 'shankhs', 
    'password': 'admin' 
    }); 
}); 

var isAuthenticated = function(req, res, next) { 
    if (req.isAuthenticated()) { 
    console.log('Authenticated'); 
    console.log(req); 
    next(); 
    } 
    console.log('redirecting to /'); 
    console.log(req.isAuthenticated()); 
    res.redirect('/'); 
}; 

app.get('/', function(req, res, next) { 
    var fileOptions = { 
    root: __dirname, 
    dotfiles: 'deny', 
    headers: { 
     'x-timestamp': Date.now(), 
     'x-sent': true 
    } 
    }; 
    res.sendFile('login.html', fileOptions, function(err) { 
    if (err) { 
     console.log(err); 
     res.status(err.status).end(); 
    } else { 
     console.log('send login.html!' + Date.now()); 
    } 
    }); 
}); 

app.get('/admin', isAuthenticated, function(req, res, next) { 
    var fileOptions = { 
    root: __dirname, 
    headers: { 
     'x-timestamp': Date.now(), 
     'x-sent': true 
    } 
    }; 
    var fileName = 'index.html'; 
    res.sendFile(fileName, fileOptions, function(err) { 
    if (err) { 
     console.log(err); 
     res.status(err.status).end(); 
    } else { 
     console.log('Send index.html' + Date.now()); 
    } 
    }); 
}); 

passport.use('login', new LocalStrategy(
    function(req, username, password, done) { 
    console.log('using passport!'); 
    console.log(req.body.username); 
    console.log(req.body.password); 
    done(null, { 
     '_id': 'Hi', 
     'username': 'shankhs', 
     'password': 'admin' 
    }); 
    } 
)); 

app.post('/login', function(req, res) { 
    console.log(req.params); 
    passport.authenticate('login', { 
    successRedirect: '/admin', 
    failureRedirect: '/', 
    failureFlash: true 
    }) 
}); 
  1. POST請求/登錄路由調用異步調用passport.authenticate。
  2. 這passport.authenticate需要一個「戰略」作爲參數
  3. 這種策略被調用返回(在我的情況)與另一「完成」異步調用沒有錯誤和用戶對象
  4. 「完成」通話結束後,serializeUser被調用並且頁面被重定向到/ admin
  5. 如果有任何後續請求或任何具有isAuthenticated鉤子的URL被調用,passport.initialize將檢查req.passport.user對象是否爲空。
  6. 如果其爲空,則認證過程再次重複。
  7. 如果它不是,passport.session調用passport.deserializeUser它創建req.user對象

我的問題是:

  1. 在 '登錄' 策略,這三者從未記錄:

    console.log('using passport!'); console.log(req.body.username); console.log(req.body.password);

那麼這是否意味着我的「登錄」策略永遠不會被調用?

  1. 類似地,serializeUser和deserializeUser中的console.logs永遠不會被調用。所以這些函數也沒有被調用?

如果我對護照庫的理解是正確的,我是否缺少任何函數調用?

感謝

回答

2

對於未來戰士:

也就是說護照應該是怎樣工作的。關於護照如何工作的詳細解釋是here

這裏缺少的東西是在/ login後調用bodyparser。你可能會認爲護照知道如何解析req.body!錯誤!它不!快4節開始身體解析器將independetly安裝和使用爲:

var bodyParser = require('body-parser'); 
app.use(bodyParser.json()); 
app.use(bodyParser.urlencoded({ 
    extended: true 
})); 

POST請求:

app.post('/login', function(req, res, next) { 
    console.log('in login post!'); 
    console.log('body parsing: ' + req.body.username + ' ' + req.body.password); 
    passport.authenticate('login', function(err, user, info) { 
    if (err) { 
     console.log('passport err: ' + err); 
     return next(err); 
    } 
    if (!user) { 
     console.log('no user found!'); 
     return res.redirect('/'); 
    } 
    req.logIn(user, function(err) { 
     if (err) { 
     console.log('login error: ' + err); 
     return next(err); 
     } 
     return res.redirect('/admin'); 
    }); 
    })(req, res, next); 
}); 

正如你所看到的,我寫了一個自定義登錄回調函數,這使得比只有successRedirect和failureRedirect更有意義且易於調試。如果沒有body-parser,自定義函數將無法工作,因爲passport不知道如何解析req.body。

護照的API文件應該提到這個!那麼,現在因爲一切都按預期運作,現在世界變得有意義了!

+0

是'(req,res,next)'在最後一行但是第二行是強制性的?因爲,我正在爲我的應用程序編寫本地策略,如果沒有它,它似乎無法工作;但是,當我通過它,它的作品!我早些時候與護照本地人一起工作過,並沒有通過它,但沒有在這一個! – Akash 2015-09-06 07:29:33

+1

是的,它是必需的。如果我沒有錯,它調用匿名方法的JavaScript方式。 – 2015-09-08 16:45:24