2012-12-18 28 views
8

Ich habe Probleme mit einigen der Theorie und Konventionen hinter einigen Node.js Frameworks. Ich bin neu bei Node.js. Ich versuche, ein Szenario einzurichten, in dem ich ein MVC-Framework habe, in dem ich eine Reihe von Controllern definiere, die grundlegende Ruhefunktionen ausführen, und einige meiner Controller-Routen erfordern eine Authentifizierung. Wenn Sie nicht authentifiziert sind, sollten Sie auf die Anmeldeseite weitergeleitet werden. Nach der Anmeldung werden Sie jedoch auf die Seite zurückgeleitet, die Sie zuvor angefordert haben. Ich habe mir einige Tutorials angeschaut und einige der Fragen zu StackOverflow angeschaut, aber ich denke, das Problem ist, dass etwas nicht einfach klickt. Ich hoffe, dass einer von euch mir etwas von der Theorie hinter dem, was hier vor sich geht, erklären kann und mir vielleicht in die richtige Richtung für mein Problem zeigen kann. Mein Code ist unten. Mein wirkliches Problem ist, dass ich dieses nächste() Paradigma nicht wirklich verstehe. Vielleicht mache ich das alles falsch und denke falsch darüber nach. Vielleicht kannst du mir auch ein paar gute Ideen mitteilen.Node.js Theorie - Node.js, Express.js, Passport.js

Edit:

======

fand ich eine Lösung. Ich beantworte meine Frage später für alle anderen, die nach Informationen suchen und dieses Problem lösen möchten.

- 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); 

- Menschen Controller

/** 
* 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-Controller

/** 
* 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-Middleware

/** 
* 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(); 

Danke Jungs im Voraus. Ich liebe die Community auf StackOverflow. Ihr seid immer so toll beim Lernen einer neuen Technologie.

+2

Nur ein Kommentar, wenn Express kann statische Dateien dienen konfiguriert werden bedeutet nicht, dass es die beste Lösung ist, verwenden Sie normalerweise nginx für dieser Zweck. –

+0

Verstanden. Dies ist nur ein erster Durchgang eingerichtet. Ich würde später zu einem HTTP-Server für statischen Inhalt konvertieren. –

+0

TJ Holowaychuk hat [ein Beispiel] (https://github.com/visionmedia/express/tree/master/examples/mvc) einer Implementierung von MVC mit Express – verybadalloc

Antwort

1

Rücksendung next sind in der Regel für die Connect Middleware. Sie übergeben die Referenz der nächsten auszuführenden Funktion. Middleware verhält sich wie Filter oder Linked-Listed-Layer (Art von Referenz), die Ihre Funktion aufruft und durchläuft, bevor sie zu Ihren Ressourcen gelangt, Logik ausführt und dann entscheidet, die nächste Middleware zu verlassen/umzuleiten. Middleware könnte eine Authentifizierung sein, wie Sie sie verwenden. Auch wenn Passport ein diskretes und gut geschriebenes Modul ist, implementieren Sie es hier als Middleware (was normal ist), was im Grunde ein Authentifizierungsfilter über Ihre ensureAuthenticated Funktion ist: Sie haben im Grunde nur Ihre eigene Middleware erstellt (Achievement Unlocked) . Normalerweise setzen Sie Ihre gesamte Middleware ein, bevor Ihre Routing-Funktionen ausgeführt werden.

Was Sie als -- DB Middleware definieren, ist keine Middleware, von dem, was ich sagen kann. Es sieht eher wie ein Modul aus, mit dem Sie getrennte Probleme versuchen (was gut ist). Ich würde das die Anfänge Ihres model Moduls nennen.

Es sieht so aus, als würden Ihre Controller schnell außer Kontrolle geraten. Ich würde vorschlagen, Routes zu erforschen.

Ich bin kein Experte in Bezug auf Node.js, Express.js und Passport.js, aber ich bin erfolgreich trennen Anliegen und Programmierung in einem teilweise bearbeiteten Projekt organisiert: https://github.com/Tzvayim/theArk/blob/master/app.js

Verwandte Themen