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
    1
    2
    E:\project> node -v
    v0. 10.30 E:\project> npm -v 1.4 . 21 E:\project> express -V 4.2 . 0




  1、建立工程

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

  


  根据提示下载依赖包:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
E:\project> cd .\nodejs-demo
E:\project\nodejs-demo> npm install
npm WARN deprecated static-favicon@1.0.2: use serve-favicon module
static-favicon@1.0.2 node_modules\static-favicon
 
debug@0.7.4 node_modules\debug
 
ejs@0.8.8 node_modules\ejs
 
cookie-parser@1.0.1 node_modules\cookie-parser
├── cookie-signature@1.0.3 └── cookie@0.1.0 morgan@1.0.1 node_modules\morgan
└── bytes@0.3.0 body-parser@1.0.2 node_modules\body-parser
├── qs@0.6.6 ├── raw-body@1.1.7 (bytes@1.0.0, string_decoder@0.10.25-1)
└── type -is@1.1.0 (mime@1.2.11)
 
express@4.2.0 node_modules\express
├── parseurl@1.0.1 ├── utils-merge@1.0.0 ├── cookie@0.1.2 ├── merge-descriptors@0.0.2 ├── escape-html@1.0.1 ├── range-parser@1.0.0 ├── fresh@0.2.2 ├── cookie-signature@1.0.3 ├── debug@0.8.1 ├── methods@1.0.0 ├── buffer-crc32@0.2.1 ├── serve-static@1.1.0 ├── path-to-regexp@0.1.2 ├── qs@0.6.6 ├── send@0.3.0 (debug@0.8.0, mime@1.2.11)
├── accepts@1.0.1 (negotiator@0.4.7, mime@1.2.11)
└── type -is@1.1.0 (mime@1.2.11)
E:\project\nodejs-demo>



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

1
E:\project\nodejs-demo> npm start > nodejs-demo@0.0.1 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——项目依赖配置及开发者信息。
 
1
2
3
4
5
6
7
8
9
10
11
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
var express = require( 'express' );
var path = require( 'path' );
var favicon = require( 'static-favicon' );
var logger = require( 'morgan' );
var cookieParser = require( 'cookie-parser' );
var bodyParser = require( 'body-parser' );
 
var routes = require( './routes/index' );
var users = require( './routes/users' );
 
var app = express();
 
// view engine setup
app.set( 'views' , path.join(__dirname, 'views' ));
app.set( 'view engine' , 'ejs' );
 
app.use(favicon());
app.use(logger( 'dev' ));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(express. static (path.join(__dirname, 'public' )));
 
app.use( '/' , routes);
app.use( '/users' , users);
 
/// catch 404 and forward to error handler
app.use( function (req, res, next) {
     var err = new Error( 'Not Found' );
     err.status = 404;
     next(err);
});
 
/// error handlers
 
// development error handler
// will print stacktrace
if (app.get( 'env' ) === 'development' ) {
     app.use( function (err, req, res, next) {
         res.status(err.status || 500);
         res.render( 'error' , {
             message: err.message,
             error: err
         });
     });
}
 
// production error handler
// no stacktraces leaked to user
app.use( function (err, req, res, next) {
     res.status(err.status || 500);
     res.render( 'error' , {
         message: err.message,
         error: {}
     });
});
 
 
module.exports = app;




  4、Ejs模板

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

1
2
3
4
5
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
2
3
4
5
6
7
8
9
<! DOCTYPE html>
< html lang = "en" >
< head >
     < meta charset = "utf-8" >
     < title ><%= title %></ title >
     <!-- Bootstrap -->
     < link href = "/stylesheets/bootstrap.min.css" rel = "stylesheet" media = "screen" >
</ head >
< body screen_capture_injected = "true" >



  index.html

 
1
2
3
4
1 <% include header.html %>
2 < h1 ><%= title %></ h1 >
3 < p >Welcome to <%= title %></ p >
4 <% include footer.html %>



    footer.html

1
2
3
4
5
6
<script src= "/javascripts/jquery.min.js" ></script>
  <script src= "/javascripts/bootstrap.min.js" ></script>
  </body>
  </html>
 
 




 重启服务,访问成功。


  6、路由

  登录设计:

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

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

 
1
2
3
4
5
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
var express = require( 'express' );
var router = express.Router();
 
/* GET home page. */
router.get( '/' , function (req, res) {
   res.render( 'index' , { title: 'Express' });
});
 
router.route( '/login' )
.get( function (req, res) {
     res.render( 'login' , { title: '用户登录' });
})
.post( function (req, res) {
     var user={
         username: 'admin' ,
         password: '123456'
     }
     if (req.body.username === user.username && req.body.password === user.password){
         res.redirect( '/home' );
     }
     res.redirect( '/login' );
});
 
router.get( '/logout' , function (req, res) {
     res.redirect( '/' );
});
 
router.get( '/home' , function (req, res) {
     var user={
         username: 'admin' ,
         password: '123456'
     }
     res.render( 'home' , { title: 'Home' , user: user });
});
 
module.exports = router;



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

  login.html

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<% include header.html %>
< div class = "container" >
     < form class = "col-sm-offset-4 col-sm-4 form-horizontal" role = "form" method = "post" >
         < fieldset >
             < legend >用户登录</ legend >
             < div class = "form-group" >
                 < label class = "col-sm-3 control-label" for = "username" >用户名</ label >
                 < div class = "col-sm-9" >
                     < input type = "text" class = "form-control" id = "username" name = "username" placeholder = "用户名" required>
                 </ div >
             </ div >
             < div class = "form-group" >
                 < label class = "col-sm-3 control-label" for = "password" >密码</ label >
                 < div class = "col-sm-9" >
                     < input type = "password" class = "form-control" id = "password" name = "password" placeholder = "密码" required>
                 </ div >
             </ div >
             < div class = "form-group" >
                 < div class = "col-sm-offset-3 col-sm-9" >
                     < button type = "submit" class = "btn btn-primary" >登录</ button >
                 </ div >
             </ div >
         </ fieldset >
     </ form >
</ div >
<% include footer.html %>



  home.html

 
1
2
3
4
1 <% include header.html %>
2 <h1>Welcome <%= user.username %>, 欢迎登录!!</h1>
3 <a class = "btn" href= "/logout" >退出</a>
4 <% include footer.html %>



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

1
2
3
4
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:

 
1
2
3
4
5
E:\project\nodejs-demo> npm install express-session
express-session@1.7.5 node_modules\express-session
├── cookie@0.1.2 ├── cookie-signature@1.0.4 ├── on-headers@1.0.0 ├── utils-merge@1.0.0 ├── parseurl@1.3.0 ├── buffer-crc32@0.2.3 ├── depd@0.4.4 ├── debug@1.0.4 (ms@0.6.2)
└── uid-safe@1.0.1 (base64-url@1.0.0, mz@1.0.0)
E:\project\nodejs-demo>



  安装中间件connect-mongodb:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
E:\project\nodejs-demo> npm install connect-mongodb
\ > kerberos@0.0.3 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 |
> bson@0.2.11 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-mongodb@1.1.5 node_modules\connect-mongodb
├── connect@1.9.2 (mime@1.2.11, formidable@1.0.15, qs@1.2.2)
└── mongodb@1.4.8 (kerberos@0.0.3, readable-stream@1.0.27-1, bson@0.2.11)
E:\project\nodejs-demo>



  安装中间件mongodb:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
E:\project\nodejs-demo> npm install mongodb -
 
 
> kerberos@0.0.3 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 |
> bson@0.2.11 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-stream@1.0.27-1 (isarray@0.0.1, string_decoder@0.10.25-1, inheri
ts@2.0.1, core-util-is@1.0.1)
└── bson@0.2.11 (nan@1.2.0)
E:\project\nodejs-demo>



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

  settings.js

 
1
2
3
4
5
6
7
8
9
module.exports = {
     COOKIE_SECRET: 'ywang1724.com' ,
     URL: 'mongodb://127.0.0.1:27017/nodedb' ,
     DB: 'nodedb' ,
     HOST: '127.0.0.1' ,
     PORT: 27017,
     USERNAME: 'admin' ,
     PASSWORD: '123456'
};



  msession.js

1
2
3
4
5
6
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
var express = require( 'express' );
var path = require( 'path' );
var favicon = require( 'static-favicon' );
var logger = require( 'morgan' );
var cookieParser = require( 'cookie-parser' );
var bodyParser = require( 'body-parser' );
 
//采用connect-mongodb中间件作为Session存储 
var session = require( 'express-session' ); 
var Settings = require( './database/settings' ); 
var MongoStore = require( 'connect-mongodb' ); 
var db = require( './database/msession' );
 
var routes = require( './routes/index' );
var users = require( './routes/users' );
 
var app = express();
 
// view engine setup
app.set( 'views' , path.join(__dirname, 'views' ));
//app.set('view engine', 'ejs');
app.engine( 'html' , require( 'ejs' ).renderFile);
app.set( 'view engine' , 'html' );
 
app.use(favicon());
app.use(logger( 'dev' ));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
//session配置
app.use(session({
     cookie: { maxAge: 600000 },
     secret: Settings.COOKIE_SECRET,
     store: new MongoStore({ 
         username: Settings.USERNAME,
         password: Settings.PASSWORD,
         url: Settings.URL,
         db: db})
}))
app.use( function (req, res, next){
     res.locals.user = req.session.user;
     next();
});
 
app.use(express. static (path.join(__dirname, 'public' )));
 
......



  修改index.js文件:

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
var express = require( 'express' );
var router = express.Router();
 
/* GET home page. */
router.get( '/' , function (req, res) {
     res.render( 'index' , { title: 'Express' });
});
 
router.route( '/login' )
.get( function (req, res) {
     res.render( 'login' , { title: '用户登录' });
})
.post( function (req, res) {
     var user = {
         username: 'admin' ,
         password: '123456'
     }
     if (req.body.username === user.username && req.body.password === user.password){
         req.session.user = user;
         res.redirect( '/home' );
     } else {
         res.redirect( '/login' );
     }
});
 
router.get( '/logout' , function (req, res) {
     req.session.user = null ;
     res.redirect( '/' );
});
 
router.get( '/home' , function (req, res) {
     res.render( 'home' , { title: 'Home' });
});
 
module.exports = router;



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


  8、页面访问控制及提示

  访问控制设计:

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

  修改index.js文件:

 
1
2
3
4
5
6
7
8
9
10
router.get( '/home' , function (req, res) {
     authentication(req, res);
     res.render( 'home' , { title: 'Home' });
});
 
function authentication(req, res) {
     if (!req.session.user) {
         return res.redirect( '/login' );
     }
}



  重启服务,访问成功。

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

 
1
2
3
4
5
6
7
8
9
10
app.use(function(req, res, next) {
    res.locals.user = req.session.user;
    varerr = req.session.error;
    deletereq.session.error;
    res.locals.message = '';
    if(err) {
        res.locals.message = '<div class="alert alert-warning">' + err + '</div>';
    }
    next();
});



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

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
var express = require( 'express' );
var router = express.Router();
 
/* GET home page. */
router.get( '/' , function (req, res) {
     res.render( 'index' , { title: 'Express' });
});
 
router.route( '/login' )
.get( function (req, res) {
     if (req.session.user) {
         res.redirect( '/home' );
     }
     res.render( 'login' , { title: '用户登录' });
})
.post( function (req, res) {
     var user = {
         username: 'admin' ,
         password: '123456'
     }
     if (req.body.username === user.username && req.body.password === user.password) {
         req.session.user = user;
         res.redirect( '/home' );
     } else {
         req.session.error='用户名或密码不正确';
        res.redirect('/login');
     }
});
 
router.get( '/logout' , function (req, res) {
     req.session.user = null ;
     res.redirect( '/' );
});
 
router.get( '/home' , function (req, res) {
     authentication(req, res);
     res.render( 'home' , { title: 'Home' });
});
 
function authentication(req, res) {
     if (!req.session.user) {
         req.session.error= '请先登录' ;
         return res.redirect( '/login' );
     }
}
 
module.exports = router;



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

1
2
3
5 <legend>用户登录</legend>
6 <%- message %>
7 <div class = "form-group" >



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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值