zoukankan      html  css  js  c++  java
  • 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 .
    odejs-demo
    E:project
    odejs-demo> npm install
    npm WARN deprecated static-favicon@1.0.2: use serve-favicon module
    static-favicon@1.0.2 node_modulesstatic-favicon
    
    debug@0.7.4 node_modulesdebug
    
    ejs@0.8.8 node_modulesejs
    
    cookie-parser@1.0.1 node_modulescookie-parser
    ├── cookie-signature@1.0.3
    └── cookie@0.1.0
    
    morgan@1.0.1 node_modulesmorgan
    └── bytes@0.3.0
    
    body-parser@1.0.2 node_modulesody-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_modulesexpress
    ├── 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
    odejs-demo>

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

    E:project
    odejs-demo> npm start
    
    > nodejs-demo@0.0.1 start E:project
    odejs-demo
    > node ./bin/www

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


      2、目录结构

    • bin——存放命令行程序。
    • node_modules——存放所有的项目依赖库。
    • public——存放静态文件,包括css、js、img等。
    • routes——存放路由文件。
    • views——存放页面文件(ejs模板)。
    • app.js——程序启动文件。
    • package.json——项目依赖配置及开发者信息。
    E:project
    odejs-demo> dir
    
    
        目录: E:project
    odejs-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
    odejs-demo> npm install bootstrap
    bootstrap@3.2.0 node_modulesootstrap
    E:project
    odejs-demo> npm install jquery
    jquery@2.1.1 node_modulesjquery
    E:project
    odejs-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
    odejs-demo> npm install express-session
    express-session@1.7.5 node_modulesexpress-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
    odejs-demo>

      安装中间件connect-mongodb:

    E:project
    odejs-demo> npm install connect-mongodb
    
    
    
    > kerberos@0.0.3 install E:project
    odejs-demo
    ode_modulesconnect-mongodb
    od
    e_modulesmongodb
    ode_moduleskerberos
    > (node-gyp rebuild 2> builderror.log) || (exit 0)
    
    |
    E:project
    odejs-demo
    ode_modulesconnect-mongodb
    ode_modulesmongodb
    ode_mo
    duleskerberos>node "C:Program Files
    odejs
    ode_modules
    pmin
    ode-gyp-bin\
    ....
    ode_modules
    ode-gypin
    ode-gyp.js" rebuild
    |
    > bson@0.2.11 install E:project
    odejs-demo
    ode_modulesconnect-mongodb
    ode_m
    odulesmongodb
    ode_modulesson
    > (node-gyp rebuild 2> builderror.log) || (exit 0)
    
    
    E:project
    odejs-demo
    ode_modulesconnect-mongodb
    ode_modulesmongodb
    ode_mo
    dulesson>node "C:Program Files
    odejs
    ode_modules
    pmin
    ode-gyp-bin\...
    .
    ode_modules
    ode-gypin
    ode-gyp.js" rebuild
    connect-mongodb@1.1.5 node_modulesconnect-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
    odejs-demo>

      安装中间件mongodb:

    E:project
    odejs-demo> npm install mongodb
    -
    
    
    > kerberos@0.0.3 install E:project
    odejs-demo
    ode_modulesmongodb
    ode_module
    skerberos
    > (node-gyp rebuild 2> builderror.log) || (exit 0)
    
    -
    E:project
    odejs-demo
    ode_modulesmongodb
    ode_moduleskerberos>node "C:Progr
    am Files
    odejs
    ode_modules
    pmin
    ode-gyp-bin\....
    ode_modules
    ode-gyp
    in
    ode-gyp.js" rebuild
    |
    > bson@0.2.11 install E:project
    odejs-demo
    ode_modulesmongodb
    ode_modules
    son
    > (node-gyp rebuild 2> builderror.log) || (exit 0)
    
    
    E:project
    odejs-demo
    ode_modulesmongodb
    ode_modulesson>node "C:Program F
    iles
    odejs
    ode_modules
    pmin
    ode-gyp-bin\....
    ode_modules
    ode-gypin
    
    ode-gyp.js" rebuild
    mongodb@1.4.8 node_modulesmongodb
    ├── 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
    odejs-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">

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

    图1 登录不成功提示

  • 相关阅读:
    一般处理程序中,禁止缓存的办法!
    在ashx处理程序中,如果返回json串数据?
    开通博客园了。
    consul
    gitlab
    swoft
    consul(转https://blog.csdn.net/junaozun/article/details/90699384)
    mac tar 解压
    redis应用场景
    redis 集群
  • 原文地址:https://www.cnblogs.com/ywang1724/p/3917085.html
Copyright © 2011-2022 走看看