用node.js建立微博

路由规划

/:首页

/u/[user]:用户的主页

/post:发表信息

/reg:用户注册

/login:用户登录

/logout:用户登出

 

在app.js中添加

其中/post、/login、/reg由于要接受表单信息,使用app.post注册路由。/login和/reg还要显示用户注册时要填的表单,所以要以app.get注册。

 

使用bootstrap

 

访问数据库

MongoDB的数据饿死是BSON,因此与javascript的亲和性很强。在MongoDB对数据的操作都是以文档为单位的。对于查询操作,我们只需指定文档的任何一个属性,就可在数据库将满足条件的所有文档筛选。

在package.json的dependencies属性中添加"mongodb": ">= 0.9.9"。然后运行npm install mongodb更新。

 

在工程的目录创建setting.js,用于保存数据库的连接信息,内容如下

module.exports = { 
  cookieSecret: ‘myblog‘, 
  db: ‘blog‘, 
  host: ‘localhost‘,
  port: 27017
}; 

其中 db 是数据库的名称,host 是数据库的地址,port是数据库的端口号,cookieSecret 用于 Cookie 加密与数据库无关,我们留作后用。

 

然后创建models文件夹并在lime创建db.js,内容如下

var settings = require(‘../settings‘),
    Db = require(‘mongodb‘).Db,
    Connection = require(‘mongodb‘).Connection,
    Server = require(‘mongodb‘).Server;

module.exports = new Db(settings.db, new Server(settings.host, settings.port), {safe: true});

 

会话支持

获得connect-mongo和express-session模块,在package.json中添加

"connect-mongo": "0.4.1",

在app.js中添加

var session = require(‘express-session‘);  //如果要使用session,需要单独包含这个模块
var MongoStore = require(‘connect-mongo‘)(session);
var settings = require(‘./settings‘);


app.use(session({  //这个要放在app(flash())(后面会添加)之前,app(flash())要放在app.use(‘/’, routes);之前
secret: settings.cookieSecret,
key: settings.db,//cookie name
cookie: {maxAge: 1000 * 60 * 60 * 24 * 30},//30 days
store: new MongoStore({
db: settings.db
})
}));

 

使用 express-session 和 connect-mongo 模块实现了将会化信息存储到mongoldb中。

secret 用来防止篡改 cookie,key 的值为 cookie 的名字,通过设置 cookie 的 maxAge 值设定 cookie 的生存期,这里我们设置 cookie 的生存期为 30 天,设置它的 store 参数为 MongoStore 实例,把会话信息存储到数据库中,以避免丢失。

 

Flash

flash 即 connect-flash 模块(https://github.com/jaredhanson/connect-flash),flash 是一个在 session 中用于存储信息的特定区域。信息写入 flash ,下一次显示完毕后即被清除。典型的应用是结合重定向的功能,确保信息是提供给下一个被渲染的页面。

 

在 package.json 添加一行代码:"connect-flash": “0.1.1"   ,然后 npm install 安装 connect-flash 模块。

修改app.js,

在 var settings = require(‘./settings‘); 后添加:var flash = require(‘connect-flash‘);

app(flash());要放在app.use(‘/’, routes);之前

 

注册响应

在 models 文件夹下新建 user.js,添加如下代码:

var mongodb = require(‘./db‘);

function User(user) {
  this.name = user.name;
  this.password = user.password;
};

module.exports = User;

//存储用户信息
User.prototype.save = function(callback) {
  //要存入数据库的用户文档
  var user = {
      name: this.name,
      password: this.password,
  };
  //打开数据库
  mongodb.open(function (err, db) {
    if (err) {
      return callback(err);//错误,返回 err 信息
    }
    //读取 users 集合
    db.collection(‘users‘, function (err, collection) {
      if (err) {
        mongodb.close();
        return callback(err);//错误,返回 err 信息
      }
      //将用户数据插入 users 集合
      collection.insert(user, {
        safe: true
      }, function (err, user) {
        mongodb.close();
        if (err) {
          return callback(err);//错误,返回 err 信息
        }
        callback(null, user[0]);//成功!err 为 null,并返回存储后的用户文档
      });
    });
  });
};

//读取用户信息
User.get = function(name, callback) {
  //打开数据库
  mongodb.open(function (err, db) {
    if (err) {
      return callback(err);//错误,返回 err 信息
    }
    //读取 users 集合
    db.collection(‘users‘, function (err, collection) {
      if (err) {
        mongodb.close();
        return callback(err);//错误,返回 err 信息
      }
      //查找用户名(name键)值为 name 一个文档
      collection.findOne({
        name: name
      }, function (err, user) {
        mongodb.close();
        if (err) {
          return callback(err);//失败!返回 err 信息
        }
        callback(null, user);//成功!返回查询的用户信息
      });
    });
  });
};

通过 User.prototype.save 实现了用户信息的存储,通过 User.get 实现了用户信息的读取。

 

在index.js最前面添加如下代码:var crypto = require(‘crypto‘),     User = require(‘../models/user.js‘);

引入 crypto 模块和 user.js 用户模型文件,crypto 是 Node.js 的一个核心模块,生成散列值来加密密码。

 

修改 index.js 中 app.post(‘/reg‘)

router.post("/reg", function(req, res) {
  console.log(req.body[‘username‘]);
  console.log(req.body[‘password‘]);
  console.log(req.body[‘password-repeat‘]);
  if(req.body[‘password-repeat‘] != req.body[‘password‘]){
    req.flash(‘error‘, ‘两次输入的密码不一致‘);
    return res.redirect(‘/reg‘);
  }  
  var md5 = crypto.createHash(‘md5‘);
  var password = md5.update(req.body.password).digest(‘base64‘);

  var newUser = new User({
    name: req.body.username,
    password: password,
  });
  //检查用户名是否已经存在
  User.get(newUser.name, function(err, user) {
    if (user) {
      err = ‘Username already exists.‘;
    }
    if (err) {
  req.flash(‘error‘, err);
  return res.redirect(‘/reg‘);
    }

    newUser.save(function(err) {
  if (err) {
    req.flash(‘error‘, err);
    return res.redirect(‘/reg‘);
  }
  req.session.user = newUser;
  req.flash(‘success‘, req.session.user.name+‘注册成功‘);
  res.redirect(‘/‘);
    });
  });  
});

 

req.body: 就是 POST 请求信息解析过后的对象,例如我们要访问 POST 来的表单内的 name="password" 域的值,只需访问 req.body[‘password‘] 或 req.body.password 即可。
res.redirect: 重定向功能,实现了页面的跳转,更多关于 res.redirect 的信息请查阅:http://expressjs.com/api.html#res.redirect 。
User:在前面的代码中,我们直接使用了 User 对象。User 是一个描述数据的对象,即 MVC 架构中的模型。前面我们使用了许多视图和控制器,这是第一次接触到模型。与视图和控制器不同,模型是真正与数据打  交道的工具,没有模型,网站就只是一个外壳,不能发挥真实的作用,因此它是框架中最根本的部分。

User.get:通过用户名获取已知用户,这里用来判断用户名是否已经存在。User.save可以将用户对象的修改写入数据库。

通过req.session.user:newUse 向会话对象写入了当前用户的信息,判断用户是否登陆。

 

修改导航部分,为已登陆用户和未登陆用户显示不同的信息

              <% if(!user) { %>
                <li><a href="/login">登入</a></li>
                <li><a href="/reg">注册</a></li>
              <%} else {  %>
                <li><a href="/logout">登出</a></li>
              <% } %>

 

页面通知

    <% if (success) { %>
      <div class="alert alert-success">
        <%= success %>
      </div>
    <% } %>
    <% if (error) { %>
      <div class="alert alert-error">
        <%= error %>
      </div>
    <% } %>

 

登陆和登出

router.get(‘/login‘, function (req, res) {
  res.render(‘login‘,{title: ‘用户登录‘,
    user: req.session.user,
    success: req.flash(‘success‘).toString(),
    error: req.flash(‘error‘).toString()
   });
});

router.post("/login",function(req,res) {
  var md5 = crypto.createHash(‘md5‘);
  var password = md5.update(req.body.password).digest(‘base64‘);

  User.get(req.body.username, function(err, user) {
    if (!user) {
      req.flash(‘error‘, ‘用户不存在‘);
      return res.redirect(‘/login‘);
    }
           
    if (user.password != password) {
      req.flash(‘error‘, ‘用户名或密码错误‘);
      return res.redirect(‘/login‘);
    }
    req.session.user = user;
    req.flash(‘success‘, req.session.user.name + ‘登录成功‘);
    
    res.redirect(‘/‘);
  });
});

router.get(‘/logout‘, function (req, res) {
  req.session.user = null;
  req.flash(‘success‘, ‘登出成功‘);
  res.redirect(‘/‘);
});

 

页面权限控制

登出功能应该只对已登陆的用户开发,注册和登入页面应阻止已登陆的用户访问。

利用路由中间件来实现。

把用户登陆状态放到路由中间件中,在每个路径前增加路由中间件。

function checkNotLogin(req, res, next) {
  if (req.session.user) {
    req.flash(‘error‘, ‘用户已经登录‘);
    return res.redirect(‘/‘);
  }
  next();
}
function checkLogin(req, res, next) {
  if (!req.session.user) {
    req.flash(‘error‘, ‘用户尚未登录‘);
    return res.redirect(‘/login‘);
  }
  next();
}
router.get("/reg",  checkNotLogin);
router.post("/reg",  checkNotLogin);

router.get("/login",  checkNotLogin);
router.post("/login",  checkNotLogin);

router.get(‘/logout‘, checkLogin);

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。