This example is based on the previous logindemo (see using cookies to stay logged in ) and we introduced MongoDB to save user data. To run this example, if the MongoDB data is going to work (see node. JS Development Primer--mongodb and Mongoose). The result of the run of the example is the same as the previous Logindemo. So, let's just analyze the changes in the project itself when the database is introduced.
Installing Mongoose
Under command-line environment, navigate to the Logindemo directory and execute the following command:
npm install mongoose --save
It will automatically help us install dependencies, and will also write mongoose as dependencies to the project's Package.json file.
Database Initialization Script Dbinit.js
Dbinit.js is used to initialize the database, create a library called Users, a collection called accounts, and insert two accounts. The code is as follows:
var crypto = require (' crypto '), var mongoose = require (' Mongoose '); Mongoose.connect (' mongodb://localhost/users '); function Hashpw (userName, pwd) {var hash = Crypto.createhash (' MD5 '); Hash.update (UserName + pwd); return hash.digest (' hex ');} var db = Mongoose.connection;db.on (' Error ', Console.error.bind (console, ' connection error: ')); var count = 2;function CheckClose () {count = Count-1; if (count==0) Mongoose.disconnect ();} Db.once (' Open ', function () {Console.log (' Mongoose opened! '); var userschema = new Mongoose. Schema ({name: {type:string, unique:true}, Hash:string, last:string}, {collection: "Accounts"} ); var User = Mongoose.model (' accounts ', Userschema); var doc = new User ({name: "admin", HASH:HASHPW ("admin", "123456"), Last: ""}); Doc.save (err, doc) {if (err) console.log (err); else Console.log (doc.name + ' saved '); CheckClose (); }); doc = new User ({name: "Foruok", HASH:HASHPW ("Foruok", "888888"), Last: ""}); Doc.savE (function (err, doc) {if (err) console.log (err); else Console.log (doc.name + ' saved '); CheckClose (); }); });
Before starting the Web site, execute "node Dbinit.js" to initialize.
In Dbinit.js, I used the Save method of the Mongoose Document object to save the newly created documents, which have been used in the "MongoDB and Mongoose" article, no longer verbose.
3. Rewrite users.js
Back up the original users.js, the new users.js as follows:
var express = require (' Express '); var router = Express. Router (); var crypto = require (' crypto '); var mongoose = require (' Mongoose '); Mongoose.connect (' mongodb://localhost/ User '); var db = Mongoose.connection;db.on (' Error ', Console.error.bind (console, ' connection error: ')); var = null; Db.once (' Open ', function () {Console.log (' Mongoose opened! '); var userschema = new Mongoose. Schema ({name: {type:string, unique:true}, Hash:string, last:string}, {collection: "Accounts"} ); User = Mongoose.model (' accounts ', Userschema);}); function Hashpw (userName, pwd) {var hash = Crypto.createhash (' MD5 '); Hash.update (UserName + pwd); return hash.digest (' hex ');} function Getlastlogintime (UserName, callback) {if (! User) {callback (""); Return } var logintime = Date (). toString (); User.findone ({Name:username}, function (Err, doc) {if (err) callback (""); else{callback (Doc.last); Update Login Time doc.update ({$set: {last:logintime}}, function (erR, Doc) {if (err) console.log ("Update Login time error:" + err); else Console.log ("Update login time for" + doc.name); }); } });} function authenticate (UserName, hash, callback) {if (! User) {callback (2); return;} var query = User.findone (). where (' name ', userName); Query.exec (err, doc) {if (err | |!doc) {console.log ("Get user error:" + err); Callback (2); return} if (Doc.hash = = = Hash) callback (0); else callback (1); });} Router.requireauthentication = function (req, res, next) {if (Req.path = = "/login") {next (); Return } if (req.cookies["Account"]! = null) {var account = req.cookies[' account ']; var user = Account.account; var hash = Account.hash; Authenticate (user, hash, function (ret) {if (ret==0) {Console.log (Req.cookies.account.account + "had logined.") ); Next (); }else{console.log ("Invalid user or PWD, redirect To/login"); Res.redirect ('/login? ') +date.now ()); } }); }else{ConSole.log ("Not login, redirect To/login"); Res.redirect ('/login? ') +date.now ()); }};router.post ('/login ', function (req, res, next) {var userName = Req.body.login_username; var hash = HASHPW (UserName, Req.body.login_password); Console.log ("login_username-" + username + "password-" + Req.body.login_password + "hash-" + hash); Authenticate (userName, hash, function (ret) {switch (ret) {case 0://success getlastlogintime (UserName, funct Ion (Lasttime) {console.log ("login OK, last-" + lasttime); Res.cookie ("account", {account:username, Hash:hash, last:lasttime}, {maxage:60000}); Res.cookie ("logined", 1, {maxage:60000}); Res.redirect ('/profile? ') +date.now ()); Console.log ("after redirect"); }); Break Case 1://password error Console.log ("password error"); Res.render (' login ', {msg: ' Password error '}); Break Case 2://user not found Console.log ("User not Found"); Res.render (' login ', {msg: ' The user name does not exist '}); Break } });}); Router.get ('/login ', function (req, res, next) {Console.log ("cookies:"); Console.log (req.cookies); if (req.cookies["Account"]! = null) {var account = req.cookies[' account ']; var user = Account.account; var hash = Account.hash; Authenticate (user, hash, function (ret) {if (ret = = 0) res.redirect ('/profile? ') +date.now ()); else Res.render (' login '); }); }else{res.render (' login '); }}); Router.get ('/logout ', function (req, res, next) {Res.clearcookie ("account"); Res.redirect ('/login? ') +date.now ());}); Router.get ('/profile ', function (req, res, next) {Res.render (' profile ', {msg: "You are logged in as:" +req.cookies["Account"].account, Title: "Login Successful", Lasttime: "Last Login:" +req.cookies["Account"].last}); Module.exports = router;
The amount of code is almost the same, but the logic is a bit more complicated. Mainly Mongoose Query database is asynchronous, originally we put the account built in memory, query is synchronous. From sync to async, the code has changed dramatically, and if you look at it, you'll see, wow, there are callback and callback nesting everywhere. Fortunately I was born in C, or I was really killed.
In order to cooperate with Mongoose's asynchronous way, Users.js almost all rewritten. Let's take the Authenticate method as an example to explain. First look at the original authenticate:
function authenticate(userName, hash){ for(var i = 0; i < userdb.length; ++i){ var user = userdb[i]; if(userName === user.userName){ if(hash === user.hash){ return 0; }else{ return 1; } } } return 2;}
This is a typical synchronization method, simple and straightforward, traversing array comparisons. And look at the new authenticate:
function authenticate(userName, hash, callback){ if(!User){ callback(2); return;} var query = User.findOne().where(‘name‘, userName); query.exec(function(err, doc){ if(err || !doc){ console.log("get user error: " + err); callback(2); return} if(doc.hash === hash) callback(0); else callback(1); });}
This is the way of asynchrony. node. JS is event-driven and is a model of the main thread + multiple worker threads (thread pool), where time-consuming operations are posted to the thread pool for execution, and then through the event notification main thread, the main thread handles the event, and the callback is invoked when appropriate. Mongoose processing the database is also the logic.
In authenticate, I use Model.findone (). Where constructs a query object, and then calls the Exec method to do queries, and exec commits the query database action, which is actually done in the online pool. At the end of the query, the event notifies the main thread to callback the function we provide.
Now, when authenticate () is called, it returns quickly, but the query is posted to the thread pool for execution, and the expected result of the caller does not come immediately, and the logic that relies on the invocation result must be deferred until the callback occurs. So the caller must retrofit the code, put some logic in the callback function, and give the callback function to the new authenticate method.
You can see the code of the Requireauthentication method, and compare the similarities and differences with the following synchronous version.
router.requireAuthentication = function(req, res, next){ if(req.path == "/login"){ next(); return; } if(req.cookies["account"] != null){ var account = req.cookies["account"]; var user = account.account; var hash = account.hash; if(authenticate(user, hash)==0){ console.log(req.cookies.account.account + " had logined."); next(); return; } } console.log("not login, redirect to /login"); res.redirect(‘/login?‘+Date.now());};
For the Mongoose Operations database, crud and the like, give two links to reference:
- Https://cnodejs.org/topic/51ff720b44e76d216afe34d9
- Http://www.cnblogs.com/aaronjs/p/4489354.html
Other articles:
- node. JS Development Primer--mongodb and Mongoose
- Get started with node. JS Development-Use cookies to stay signed in
- Getting Started with node. JS-Using ANGULARJS built-in services
- node. JS Development Primer--angular Simple Example
- Introduction to node. JS Development-Using ANGULARJS
- Getting Started with node. JS Development-Using the Jade template engine
- node. JS Development Starter--express Routing and middleware
- node. JS Development Primer--express Installation and use
- node. JS Development Primer--http File Server
- node. JS Development Primer--helloworld Re-analysis
- Introduction to node. JS Development--Environment building and HelloWorld
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
node. JS get started-transform Logindemo with MongoDB