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

来源:互联网 发布:阳光民间借贷网络借贷 编辑:程序博客网 时间:2024/06/06 02:46

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

目录

  •   开发环境
  •   1、建立工程
  •   2、目录结构
  •   3、Express配置文件
  •   4、Ejs模板
  •   5、安装常用库及页面分离
  •   6、路由
  •   7、session
  •   8、页面访问控制及提示
  •   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.30E:\project> npm -v 1.4.21E:\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> npminstall
    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) {
        varerr = 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 bootstrapbootstrap@3.2.0 node_modules\bootstrapE:\project\nodejs-demo> npm install jqueryjquery@2.1.1 node_modules\jqueryE:\project\nodejs-demo>

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

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

      header.html

     
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <!DOCTYPE html>
    <htmllang="en">
    <head>
        <metacharset="utf-8">
        <title><%= title %></title>
        <!-- Bootstrap -->
        <linkhref="/stylesheets/bootstrap.min.css"rel="stylesheet"media="screen">
    </head>
    <bodyscreen_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不需要登录,可以直接访问。/homehome.html必须用户登录以后,才可以访问。/loginlogin.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) {
        varuser={
            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) {
        varuser={
            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 %>
    <divclass="container">
        <formclass="col-sm-offset-4 col-sm-4 form-horizontal"role="form"method="post">
            <fieldset>
                <legend>用户登录</legend>
                <divclass="form-group">
                    <labelclass="col-sm-3 control-label"for="username">用户名</label>
                    <divclass="col-sm-9">
                        <inputtype="text"class="form-control"id="username"name="username"placeholder="用户名"required>
                    </div>
                </div>
                <divclass="form-group">
                    <labelclass="col-sm-3 control-label"for="password">密码</label>
                    <divclass="col-sm-9">
                        <inputtype="password"class="form-control"id="password"name="password"placeholder="密码"required>
                    </div>
                </div>
                <divclass="form-group">
                    <divclass="col-sm-offset-3 col-sm-9">
                        <buttontype="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><ahref="/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> npminstall connect-mongodb
    \ > kerberos@0.0.3install E:\project\nodejs-demo\node_modules\connect-mongodb\nod
    e_modules\mongodb\node_modules\kerberos > (node-gyp rebuild 2> builderror.log) || (exit0) | 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) || (exit0)
     
     
    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> npminstall mongodb -
     
     
    > kerberos@0.0.3 install E:\project\nodejs-demo\node_modules\mongodb\node_module
    s\kerberos > (node-gyp rebuild 2> builderror.log) || (exit0) - 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) || (exit0)
     
     
    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 varSettings = require('./settings');
    2 varDb = require('mongodb').Db;
    3 varServer = require('mongodb').Server;
    4 vardb = 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) {
        varuser = {
            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) {
            returnres.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) {
        varuser = {
            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='请先登录';
            returnres.redirect('/login');
        }
    }
     
    module.exports = router;



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

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



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

    0 0