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