Node.js理论 – Node.js,Express.js,Passport.js

我正在为一些Node.js框架背后的一些理论和惯例而苦恼。 我是Node.js的新手 我试图build立一个场景,我有一个MVC框架,我定义了一组控制器来做基本的restfunction,我的一些控制器路由需要authentication。 如果您没有通过身份validation,它应该会将您发送到login页面,但在您login后,会将您返回到之前请求的页面。 我已经看了一堆教程,我已经看了一些关于StackOverflow的问题,但是我认为问题在于有些东西只是不点击而已。 我希望你们中的一个能够向我解释一些正在发生的事情背后的理论,也许我指出我的问题是正确的。 我的代码如下。 我真正的问题是我不太明白这个下一个()范例。 也许我甚至做这一切都是错误的,思考错误的方式。 也许你可以让我介绍一些好的想法。

编辑:

======

我find了解决scheme。 稍后我会回答我的问题,以供任何可能希望获得一些信息并解决此问题的人使用。

– Server.js

/** * Clancy server implementation (using Express) */ require('console-trace')({ always: true, right: true, colors: true }) /** * Include our server's needed objects. **/ var express = require('express'); var _ = require('underscore'); var cons = require('consolidate'); passport = require('passport'), LocalStrategy = require('passport-local').Strategy; var db = require('./lib/db'); var colors = require('colors'); var Users = db.users; var People = require('./controllers/People'); var Login = require('./controllers/Login'); /** * This provides our MVC context object **/ var app = express(); /** * This is our router definition for the server **/ app.engine('html', cons.underscore); // set .html as the default extension app.set('view engine', 'html'); app.set('views', __dirname + '/views'); /** * Set up the server to allow static content, cookies, session, and * parsing the server. Also, we initialize authentication and our * routing mechanism. * */ app.configure(function () { app.use('/static', express.static(__dirname + "/webapp")); app.use(express.cookieParser()); app.use(express.bodyParser()); app.use(express.session({ secret: 'keyboard cat' })); app.use(passport.initialize()); app.use(passport.session()); app.use(app.router); }); /** * This lets authentication know how it should store * and grab users from a request to pass to a mapping * function. */ passport.serializeUser(function (user, done) { done(null, user._id); }); passport.deserializeUser(function (id, done) { Users.findOne({ _id: db.bson.ObjectID(id) }, function (err, user) { done(err, user); }); }); /** * This sets up which authentication strategies we support. * as of right now, LocalStrategy (our own username/password) * is all we support. * */ passport.use(new LocalStrategy( function (username, password, done) { Users.findOne({ username: username }, function (err, user) { if (err) { return done(err); } if (!user) { return done(null, false, { message: 'Incorrect username.' }); } if (!(user.password == password)) { return done(null, false, { message: 'Incorrect password.' }); } console.info(user.password + " " + password.yellow); console.info(!(user.password == password).yellow); console.info(user._id); return done(null, user); }); })); /** * Path mapping */ // Index mapping app.get('/', function (req, resp) { resp.render('index', { title: "Welcome!" }); }); // Allow login, and set up the dependency for passport. Login.setPassport(passport); app.get("/login", Login.loginForm); app.get("/login/error", Login.loginForm); app.post('/login', passport.authenticate('local', function (req, res, next) { passport.authenticate('local', function (err, user, info) { // This is the default destination upon successful login. var redirectUrl = '/people'; if (err) { return next(err); } if (!user) { return res.redirect('/'); } // If we have previously stored a redirectUrl, use that, // otherwise, use the default. if (req.session.redirectUrl) { redirectUrl = req.session.redirectUrl; req.session.redirectUrl = null; } req.logIn(user, function (err) { if (err) { return next(err); } }); res.redirect(redirectUrl); })(req, res, next); })); app.get('/logout', Login.logout); // People Controller has a dependency on the Passport library People.setPassport(passport); // These are our definitions for paths the People Controller can handle. app.get("/people", People.list); app.get("/people/:id", People.get); // These are the error handler mappings. app.use(function (req, res, next) { // the status option, or res.statusCode = 404 // are equivalent, however with the option we // get the "status" local available as well res.render('404', { status: 404, url: req.url }); }); app.use(function (err, req, res, next) { // we may use properties of the error object // here and next(err) appropriately, or if // we possibly recovered from the error, simply next(). console.error(("ERROR: " + err.toString()).red); res.render('500', { status: err.status || 500, error: err }); }); app.listen(3000); console.info('The Clancy server is listening on port: 3000'.green); 

– 人员控制器

 /** * People Controller */ var db = require('../lib/db'); var auth = require('../lib/authUtils'); /** * People constructor. * =================== * The people constructor has dependencies on the database, * and on the Passport middleware. The db object doesn't * care about maintaining state, so we can just include that * here, however the Passport plugin needs to have all of the * stuff the server defines. So, it's passed in. */ function People(){ var passport; } People.prototype = { list: function(req, resp){ auth.ensureAuth(req, resp); console.info("user info: " + user._id); resp.render('index', { title: "User", users: [1,2,3] }); }, get: function(req, resp){ console.log('> get person' + req.params.id); db.users.find( {_id: db.bson.ObjectID(id)}, function(err, users){ if(err || !users) console.log("No user found"); resp.send(users); }); }, setPassport: function(pass){ this.passport = pass; }, getPassport: function(){ return this.passport; } } module.exports = new People(); 

– login控制器

 /** * People Controller */ /** * Login constructor. * =================== * The Login constructor has dependencies on the Passport middleware. * The db object doesn't care about maintaining state, so we can just * include that here, however the Passport plugin needs to have all * of the stuff the server defines. So, it's passed in. */ function Login(){ var passport; } var l = Login.prototype; Login.prototype = { loginForm: function(req, resp){ var url = require('url').parse(req.url, true); console.info('url string: ' + url.pathname.yellow); if(url.pathname === '/login/error') { resp.render('login', { title: "Login to FormPickle.com", message: "Your username or password was incorrect." }); } console.info('Trying to login'.yellow); resp.render('login', { title: "Login to FormPickle.com", message: "" }); }, setPassport: function(pass){ l.passport = pass; }, getPassport: function(){ return l.passport; }, logout: function(req, resp){ req.logout(); resp.render('logout'); } } module.exports = new Login(); 

– 数据库中间件

 /** * DB */ var databaseURI = "localhost:27017/clancy"; var collections = ["users", "forms"]; var db = require("mongojs").connect(databaseURI, collections); module.exports = db; 

– AuthUtils.js

 /*** * Define a middleware function for authenticated routes to store the original URL * */ function Auth(){ }; Auth.prototype = { ensureAuth: ensureAuthenticated(req, resp, next) } var ensureAuthenticated = function (req, res, next) { if (req.isAuthenticated()) { return next(); } // If the user is not authenticated, then we will start the authentication // process. Before we do, let's store this originally requested URL in the // session so we know where to return the user later. req.session.redirectUrl = req.url; // Resume normal authentication... logger.info('User is not authenticated.'); req.flash("warn", "You must be logged-in to do that."); res.redirect('/login'); } module.exports = new Auth(); 

谢谢你们提前。 我喜欢StackOverflow上的社区。 学习新技术的时候,你们总是那么棒。

next通常是Connect中间件。 你传递下一个函数的引用来执行。 中间件就像filter,或链接列出的层(通过引用types),你的函数在获取资源之前调用并遵循,执行逻辑,然后决定退出/redirect或转到下一个中​​间件。 中间件可能是身份validation,比如你正在使用。 尽pipePassport是一个离散的,写得很好的模块,但是在这里实现它作为中间件(这是正常的),它基本上是一个通过ensureAuthenticated函数的authenticationfilter:你基本上只是在那里创build了自己的中间件(Achievement Unlocked) 。 在执行路由function之前,您通常会把所有的中间件都放好。

你所定义的是什么-- DB Middleware不是中间件,据我所知。 它看起来更像是一个模块,你正在尝试单独的关注(这是好的)。 我会打电话给你的model模块的开始。

看起来你的控制器可能会很快失控。 我build议研究Routes

我不是任何关于Node.js,Express.js和Passport.js的专家,但是我成功地分离了在部分工作的项目中组织的关注和编码: https : //github.com/Tzvayim/ theArk /斑点/主/ app.js