我正在爲某些Node.js框架背後的一些理論和約定而掙扎。我是Node.js的新手。我試圖建立一個場景,我有一個MVC框架,我定義了一組控制器來完成基本的休息功能,而我的一些控制器路由需要認證。如果您沒有通過身份驗證,它應該會將您發送到登錄頁面,但在您登錄後,會將您發送回您以前請求的頁面。我已經看了一大堆教程,我已經看了一些關於StackOverflow的問題,但我認爲問題在於某些東西只是不點擊而已。我希望你們中的一個能夠向我解釋發生了什麼的一些理論,也許可以指出我的問題是正確的。我的代碼如下。我真正的問題是我不太瞭解這個下一個()範例。也許我甚至全都做錯了,並以錯誤的方式思考它。也許你可以讓我介紹一些好的想法。Node.js理論 - Node.js,Express.js,Passport.js
編輯:
======
我找到了解決辦法。稍後我會回答我的問題,以供任何可能希望獲得一些信息並解決該問題的人使用。
- 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();
- 登錄控制器
/**
* 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中間件
/**
* 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上的社區。學習新技術時,你們總是非常棒。
只是一個評論,如果express可以配置爲提供靜態文件並不意味着這是最好的解決方案,您通常使用nginx for這個目的。 –
瞭解。這只是一個初始傳球設置。我稍後將轉換爲靜態內容的HTTP服務器。 –
TJ Holowaychuk使用快速實現MVC [示例](https://github.com/visionmedia/express/tree/master/examples/mvc) – verybadalloc