NodeJS学习笔记(一)——搭建开发框架Express,实现Web网站登录验证

  JS是脚本语言,脚本语言都需要一个解析器才能运行。对于写在HTML页面里的JS,浏览器充当了解析器的角色。而对于需要独立运行的JS,NodeJS就是一个解析器。每一种解析器都是一个运行环境,不但允许JS定义各种数据结构,进行各种计算,还允许JS使用运行环境提供的内置对象和方法做一些事情。例如运行在浏览器中的JS的用途是操作DOM,浏览器就提供了document之类的内置对象。而运行在NodeJS中的JS的用途是操作磁盘文件或搭建HTTP服务器,NodeJS就相应提供了fs、http等内置对象。Express作为NodeJS的Web应用框架,可以帮助我们快速开发Web网站。


  开发环境

  • NodeJS:v0.10.30
  • npm:1.4.21
  • OS:Win7旗舰版 32bit
  • Express:4.2.0
  • MongoDB:2.6.3
E:\project> node -v

v0.10.30

E:\project> npm -v

1.4.21

E:\project> express -V

4.2.0

  1、建立工程

  使用express命令建立工程,并支持ejs:

E:\project> express -e nodejs-demo



   create : nodejs-demo

   create : nodejs-demo/package.json

   create : nodejs-demo/app.js

   create : nodejs-demo/public

   create : nodejs-demo/public/javascripts

   create : nodejs-demo/public/images

   create : nodejs-demo/public/stylesheets

   create : nodejs-demo/public/stylesheets/style.css

   create : nodejs-demo/routes

   create : nodejs-demo/routes/index.js

   create : nodejs-demo/routes/users.js

   create : nodejs-demo/views

   create : nodejs-demo/views/index.ejs

   create : nodejs-demo/views/error.ejs

   create : nodejs-demo/bin

   create : nodejs-demo/bin/www



   install dependencies:

     $ cd nodejs-demo && npm install



   run the app:

     $ DEBUG=nodejs-demo ./bin/www



E:\project>

  根据提示下载依赖包:

E:\project> cd .\nodejs-demo

E:\project\nodejs-demo> npm install

npm WARN deprecated static[email protected]: use serve-favicon module

static[email protected] node_modules\static-favicon



debug@0.7.4 node_modules\debug



ejs@0.8.8 node_modules\ejs



cookie[email protected] node_modules\cookie-parser

├── cookie[email protected]

└── cookie@0.1.0



morgan@1.0.1 node_modules\morgan

└── bytes@0.3.0



body[email protected] node_modules\body-parser

├── qs@0.6.6

├── raw[email protected] ([email protected], [email protected])

└── type-is@1.1.0 ([email protected])



express@4.2.0 node_modules\express

├── parseurl@1.0.1

├── utils[email protected]

├── cookie@0.1.2

├── merge[email protected]

├── escape[email protected]

├── range[email protected]

├── fresh@0.2.2

├── cookie[email protected]

├── debug@0.8.1

├── methods@1.0.0

├── buffer[email protected]

├── serve[email protected]

├── path[email protected]

├── qs@0.6.6

├── send@0.3.0 ([email protected], [email protected])

├── accepts@1.0.1 ([email protected], [email protected])

└── type-is@1.1.0 ([email protected])

E:\project\nodejs-demo>

  工程建立成功,启动服务:

E:\project\nodejs-demo> npm start



> [email protected] start E:\project\nodejs-demo

> node ./bin/www

  本地3000端口被打开,在浏览器地址栏输入localhost:3000,访问成功。


  2、目录结构

  • bin——存放命令行程序。
  • node_modules——存放所有的项目依赖库。
  • public——存放静态文件,包括css、js、img等。
  • routes——存放路由文件。
  • views——存放页面文件(ejs模板)。
  • app.js——程序启动文件。
  • package.json——项目依赖配置及开发者信息。
E:\project\nodejs-demo> dir





    目录: E:\project\nodejs-demo





Mode                LastWriteTime     Length Name

----                -------------     ------ ----

d----         2014/8/16     21:55            bin

d----         2014/8/16     22:03            node_modules

d----         2014/8/16     21:55            public

d----         2014/8/16     21:55            routes

d----         2014/8/16     21:55            views

-a---         2014/8/16     21:55       1375 app.js

-a---         2014/8/16     21:55        327 package.json


  3、Express配置文件

  打开app.js:

 1 var express = require('express');

 2 var path = require('path');

 3 var favicon = require('static-favicon');

 4 var logger = require('morgan');

 5 var cookieParser = require('cookie-parser');

 6 var bodyParser = require('body-parser');

 7 

 8 var routes = require('./routes/index');

 9 var users = require('./routes/users');

10 

11 var app = express();

12 

13 // view engine setup

14 app.set('views', path.join(__dirname, 'views'));

15 app.set('view engine', 'ejs');

16 

17 app.use(favicon());

18 app.use(logger('dev'));

19 app.use(bodyParser.json());

20 app.use(bodyParser.urlencoded());

21 app.use(cookieParser());

22 app.use(express.static(path.join(__dirname, 'public')));

23 

24 app.use('/', routes);

25 app.use('/users', users);

26 

27 /// catch 404 and forward to error handler

28 app.use(function(req, res, next) {

29     var err = new Error('Not Found');

30     err.status = 404;

31     next(err);

32 });

33 

34 /// error handlers

35 

36 // development error handler

37 // will print stacktrace

38 if (app.get('env') === 'development') {

39     app.use(function(err, req, res, next) {

40         res.status(err.status || 500);

41         res.render('error', {

42             message: err.message,

43             error: err

44         });

45     });

46 }

47 

48 // production error handler

49 // no stacktraces leaked to user

50 app.use(function(err, req, res, next) {

51     res.status(err.status || 500);

52     res.render('error', {

53         message: err.message,

54         error: {}

55     });

56 });

57 

58 

59 module.exports = app;

  4、Ejs模板

  修改app.js,让ejs模板文件使用扩展名为html的文件:

13 // view engine setup

14 app.set('views', path.join(__dirname, 'views'));

15 //app.set('view engine', 'ejs');

16 app.engine('html', require('ejs').renderFile);

17 app.set('view engine', 'html');

  修改完成后,重命名views/index.ejs为views/index.html。重启服务,访问成功。


  5、安装常用库及页面分离

  添加bootstrap和jQuery:

E:\project\nodejs-demo> npm install bootstrap

bootstrap@3.2.0 node_modules\bootstrap

E:\project\nodejs-demo> npm install jquery

jquery@2.1.1 node_modules\jquery

E:\project\nodejs-demo>

  接下来,把index.html分成三个部分:

  • header.html——页面头部区域。
  • index.html——页面内容区域。
  • footer.html——页面底部区域。

  header.html

1 <!DOCTYPE html>

2 <html lang="en">

3 <head>

4     <meta charset="utf-8">

5     <title><%= title %></title>

6     <!-- Bootstrap -->

7     <link href="/stylesheets/bootstrap.min.css" rel="stylesheet" media="screen">

8 </head>

9 <body screen_capture_injected="true">

  index.html

1 <% include header.html %>

2 <h1><%= title %></h1>

3 <p>Welcome to <%= title %></p>

4 <% include footer.html %>

  footer.html

1     <script src="/javascripts/jquery.min.js"></script>

2     <script src="/javascripts/bootstrap.min.js"></script>

3 </body>

4 </html>

  重启服务,访问成功。


  6、路由

  登录设计:

访问路径 页面 描述
/ index.html 不需要登录,可以直接访问。
/home home.html 必须用户登录以后,才可以访问。
/login login.html 登录页面,用户名密码输入正确,自动跳转到home.html。
/logout 退出登录后,自动跳转到index.html。

  打开app.js文件,增加路由配置:

26 app.use('/', routes);

27 app.use('/users', users);

28 app.use('/login', routes);

29 app.use('/logout', routes);

30 app.use('/home', routes);

  打开routes/index.js文件,添加对应方法:

 1 var express = require('express');

 2 var router = express.Router();

 3 

 4 /* GET home page. */

 5 router.get('/', function(req, res) {

 6   res.render('index', { title: 'Express' });

 7 });

 8 

 9 router.route('/login')

10 .get(function(req, res) {

11     res.render('login', { title: '用户登录' });

12 })

13 .post(function(req, res) {

14     var user={

15         username: 'admin',

16         password: '123456'

17     }

18     if(req.body.username === user.username && req.body.password === user.password){

19         res.redirect('/home');

20     }

21     res.redirect('/login');

22 });

23 

24 router.get('/logout', function(req, res) {

25     res.redirect('/');

26 });

27 

28 router.get('/home', function(req, res) {

29     var user={

30         username:'admin',

31         password:'123456'

32     }

33     res.render('home', { title: 'Home', user: user });

34 });

35 

36 module.exports = router;

  创建views/login.html和views/home.html两个文件:

  login.html

 1 <% include header.html %>

 2 <div class="container">

 3     <form class="col-sm-offset-4 col-sm-4 form-horizontal" role="form" method="post">

 4         <fieldset>

 5             <legend>用户登录</legend>

 6             <div class="form-group">

 7                 <label class="col-sm-3 control-label" for="username">用户名</label>

 8                 <div class="col-sm-9">

 9                     <input type="text" class="form-control" id="username" name="username" placeholder="用户名" required>

10                 </div>

11             </div>

12             <div class="form-group">

13                 <label class="col-sm-3 control-label" for="password">密码</label>

14                 <div class="col-sm-9">

15                     <input type="password" class="form-control" id="password" name="password" placeholder="密码" required>

16                 </div>

17             </div>

18             <div class="form-group">

19                 <div class="col-sm-offset-3 col-sm-9">

20                     <button type="submit" class="btn btn-primary">登录</button>

21                 </div>

22             </div>

23         </fieldset>

24     </form>

25 </div>

26 <% include footer.html %>

  home.html

1 <% include header.html %>

2 <h1>Welcome <%= user.username %>, 欢迎登录!!</h1>

3 <a class="btn" href="/logout">退出</a>

4 <% include footer.html %>

  修改index.html,增加登录链接:

1 <% include header.html %>

2     <h1>Welcome to <%= title %></h1>

3     <p><a href="/login">登录</a></p>

4 <% include footer.html %>

  路由及页面已准备好,重启服务,访问成功。


  7、session

  安装中间件express-session:

E:\project\nodejs-demo> npm install express-session

express[email protected] node_modules\express-session

├── cookie@0.1.2

├── cookie[email protected]

├── on[email protected]

├── utils[email protected]

├── parseurl@1.3.0

├── buffer[email protected]

├── depd@0.4.4

├── debug@1.0.4 ([email protected])

└── uid[email protected] ([email protected], [email protected])

E:\project\nodejs-demo>

  安装中间件connect-mongodb:

E:\project\nodejs-demo> npm install connect-mongodb

\





> [email protected] install E:\project\nodejs-demo\node_modules\connect-mongodb\nod

e_modules\mongodb\node_modules\kerberos

> (node-gyp rebuild 2> builderror.log) || (exit 0)



|

E:\project\nodejs-demo\node_modules\connect-mongodb\node_modules\mongodb\node_mo

dules\kerberos>node "C:\Program Files\nodejs\node_modules\npm\bin\node-gyp-bin\\

..\..\node_modules\node-gyp\bin\node-gyp.js" rebuild

|

> [email protected] install E:\project\nodejs-demo\node_modules\connect-mongodb\node_m

odules\mongodb\node_modules\bson

> (node-gyp rebuild 2> builderror.log) || (exit 0)





E:\project\nodejs-demo\node_modules\connect-mongodb\node_modules\mongodb\node_mo

dules\bson>node "C:\Program Files\nodejs\node_modules\npm\bin\node-gyp-bin\\..\.

.\node_modules\node-gyp\bin\node-gyp.js" rebuild

connect[email protected] node_modules\connect-mongodb

├── connect@1.9.2 ([email protected], [email protected], [email protected])

└── mongodb@1.4.8 ([email protected], [email protected], [email protected])

E:\project\nodejs-demo>

  安装中间件mongodb:

E:\project\nodejs-demo> npm install mongodb

-





> [email protected] install E:\project\nodejs-demo\node_modules\mongodb\node_module

s\kerberos

> (node-gyp rebuild 2> builderror.log) || (exit 0)



-

E:\project\nodejs-demo\node_modules\mongodb\node_modules\kerberos>node "C:\Progr

am Files\nodejs\node_modules\npm\bin\node-gyp-bin\\..\..\node_modules\node-gyp\b

in\node-gyp.js" rebuild

|

> [email protected] install E:\project\nodejs-demo\node_modules\mongodb\node_modules\b

son

> (node-gyp rebuild 2> builderror.log) || (exit 0)





E:\project\nodejs-demo\node_modules\mongodb\node_modules\bson>node "C:\Program F

iles\nodejs\node_modules\npm\bin\node-gyp-bin\\..\..\node_modules\node-gyp\bin\n

ode-gyp.js" rebuild

mongodb@1.4.8 node_modules\mongodb

├── kerberos@0.0.3

├── readable[email protected] ([email protected], [email protected], inheri

ts@2.0.1, core-util-is@1.0.1)

└── bson@0.2.11 ([email protected])

E:\project\nodejs-demo>

  添加database/settings.js和database/msession.js这两个文件:

  settings.js

1 module.exports = {

2     COOKIE_SECRET: 'ywang1724.com', 

3     URL: 'mongodb://127.0.0.1:27017/nodedb',

4     DB: 'nodedb', 

5     HOST: '127.0.0.1',

6     PORT: 27017,

7     USERNAME: 'admin',

8     PASSWORD: '123456'

9 };

  msession.js

1 var Settings = require('./settings');

2 var Db = require('mongodb').Db;

3 var Server = require('mongodb').Server; 

4 var db = new Db(Settings.DB, new Server(Settings.HOST, Settings.PORT, {auto_reconnect:true, native_parser: true}),{safe: false});

5 

6 module.exports = db;

  修改app.js文件:

 1 var express = require('express');

 2 var path = require('path');

 3 var favicon = require('static-favicon');

 4 var logger = require('morgan');

 5 var cookieParser = require('cookie-parser');

 6 var bodyParser = require('body-parser');

 7 

 8 //采用connect-mongodb中间件作为Session存储  

 9 var session = require('express-session');  

10 var Settings = require('./database/settings');  

11 var MongoStore = require('connect-mongodb');  

12 var db = require('./database/msession'); 

13 

14 var routes = require('./routes/index');

15 var users = require('./routes/users');

16 

17 var app = express();

18 

19 // view engine setup

20 app.set('views', path.join(__dirname, 'views'));

21 //app.set('view engine', 'ejs');

22 app.engine('html', require('ejs').renderFile);

23 app.set('view engine', 'html');

24 

25 app.use(favicon());

26 app.use(logger('dev'));

27 app.use(bodyParser.json());

28 app.use(bodyParser.urlencoded());

29 app.use(cookieParser());

30 //session配置

31 app.use(session({

32     cookie: { maxAge: 600000 },

33     secret: Settings.COOKIE_SECRET,

34     store: new MongoStore({  

35         username: Settings.USERNAME,

36         password: Settings.PASSWORD,

37         url: Settings.URL,

38         db: db})

39 }))

40 app.use(function(req, res, next){

41     res.locals.user = req.session.user;

42     next();

43 });

44 

45 app.use(express.static(path.join(__dirname, 'public')));

46 

47 ......

  修改index.js文件:

 1 var express = require('express');

 2 var router = express.Router();

 3 

 4 /* GET home page. */

 5 router.get('/', function(req, res) {

 6     res.render('index', { title: 'Express' });

 7 });

 8 

 9 router.route('/login')

10 .get(function(req, res) {

11     res.render('login', { title: '用户登录' });

12 })

13 .post(function(req, res) {

14     var user = {

15         username: 'admin',

16         password: '123456'

17     }

18     if(req.body.username === user.username && req.body.password === user.password){

19         req.session.user = user;

20         res.redirect('/home');

21     } else {

22         res.redirect('/login');

23     }

24 });

25 

26 router.get('/logout', function(req, res) {

27     req.session.user = null;

28     res.redirect('/');

29 });

30 

31 router.get('/home', function(req, res) {

32     res.render('home', { title: 'Home' });

33 });

34 

35 module.exports = router;

  本地安装数据库MongoDB,新建用户nodedb。重启服务,访问成功。


  8、页面访问控制及提示

  访问控制设计:

访问路径 描述
/ 任何人都可以访问,不需要认证。
/home 拦截get请求,调用authentication()进行认证,不通过则自动跳转到登录页面。
/login 任何人都可以访问,不需要认证。
/logout 任何人都可以访问,不需要认证。

  修改index.js文件:

34 router.get('/home', function(req, res) {

35     authentication(req, res);

36     res.render('home', { title: 'Home' });

37 });

38 

39 function authentication(req, res) {

40     if (!req.session.user) {

41         return res.redirect('/login');

42     }

43 }

  重启服务,访问成功。

  添加页面提示,修改app.js文件,增加res.locals.message:

40 app.use(function(req, res, next) {

41     res.locals.user = req.session.user;

42     var err = req.session.error;

43     delete req.session.error;

44     res.locals.message = '';

45     if (err) {

46         res.locals.message = '<div class="alert alert-warning">' + err + '</div>';

47     }

48     next();

49 });

  修改index.js文件,增加req.session.error:

 1 var express = require('express');

 2 var router = express.Router();

 3 

 4 /* GET home page. */

 5 router.get('/', function(req, res) {

 6     res.render('index', { title: 'Express' });

 7 });

 8 

 9 router.route('/login')

10 .get(function(req, res) {

11     if (req.session.user) {

12         res.redirect('/home');

13     }

14     res.render('login', { title: '用户登录' });

15 })

16 .post(function(req, res) {

17     var user = {

18         username: 'admin',

19         password: '123456'

20     }

21     if (req.body.username === user.username && req.body.password === user.password) {

22         req.session.user = user;

23         res.redirect('/home');

24     } else {

25         req.session.error='用户名或密码不正确';

26         res.redirect('/login');

27     }

28 });

29 

30 router.get('/logout', function(req, res) {

31     req.session.user = null;

32     res.redirect('/');

33 });

34 

35 router.get('/home', function(req, res) {

36     authentication(req, res);

37     res.render('home', { title: 'Home' });

38 });

39 

40 function authentication(req, res) {

41     if (!req.session.user) {

42         req.session.error='请先登录';

43         return res.redirect('/login');

44     }

45 }

46 

47 module.exports = router;

  修改login.html,增加<%- message %>:

5 <legend>用户登录</legend>

6 <%- message %>

7 <div class="form-group">

  重启服务,访问成功。输入错误用户名密码:

NodeJS学习笔记(一)——搭建开发框架Express,实现Web网站登录验证

图1 登录不成功提示

你可能感兴趣的:(express)