上一节准备好了数据库访问和会话存储的相关信息,这一节实现网站的用户注册和登录功能页面。
一,注册页面
先设计用户注册页面的表单,创建一个views/reg.ejs文件:
<form class="form-horizontal" method="post">
<fieldset>
<legend>用户注册</legend>
<div class="control-group">
<label class="control-label" for="username">用户名</label>
<div class="controls">
<input class="input-xlarge" type="text" name="username" id="username">
<p class="help-block">你的账户名称用于登录和显示</p>
</div>
</div>
<div class="control-group">
<label class="control-label" for="password">口令</label>
<div class="controls">
<input class="input-xlarge" type="password" name="password" id="password">
</div>
</div>
<div class="control-group">
<label class="control-label" for="password-repeat">确认口令</label>
<div class="controls">
<input class="input-xlarge" type="password" name="password-repeat" id="password-repeat">
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">注册</button>
</div>
</fieldset>
</form>
这个表单有3个输入单元,username用户名,password密码,和password-repeat确认密码,表单请求方式是POST;在浏览器地址栏中打开http://localhost:3000/reg,注册页面效果:
当然现在注册提交是没有效果的,因为还没有实现POST请求发送后的功能;接下来实现注册响应,在app.js中添加:
app.post("/reg",function(req,res,next){
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 = "用户已经存在";
}
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", "注册成功");
res.redirect("/");
});
});
})
req.body 就是POST请求信息解析过后的对象,例如要访问用户提交的password域的值,只要req.body["password"]就行。
req.flash是express提供的工具,通过它保存的变量只会在用户当前和下一次的请求被访问,之后会被清除,通过它可以很方便的实现页面的通知和错误信息显示功能。
res.redirect是重定向功能,通过它会向用户返回一个 303 see other状态,通过浏览器转向相应页面。
crypto是Node.js的一个核心模块,功能是加密并生成各种散列值,使用它之前要引入它,var crypto = require("crypto") 。
User是我们设计的用户对象,使用它需要通过 var User =require("../models/User")引用。
User.get的功能是通过用户名获取已知的用户,在这里我们判断用户名是否已经存在,User.save可以将用户对象的修改写入数据库。
通过req.session.user = newUser 向会话对象写入当前用户的信息,在后面通过它判断用户是否已经登录。
二,用户模型
在前面的代码中,我们直接是哟用来User对象,User是一个描述数据的对象,即MVC架构中的模型,前面使用了很多视图和控制器,这是第一次接触模型,与视图和控制器不同的是,模型是真正和数据打交道的工具,没有模型,网站就是一个空壳。因此它是框架中最根本的部分,网站的核心,现在实现User模型,
在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 save(callback) {
//存入MongoDB的文档
var user = {
name: this.name,
password: this.password,
};
mongodb.open(function(err, db) {
if (err) {
return callback(err);
}
//读取users集合
db.collection("users", function(err, collection) {
if (err) {
mongodb.close();
return callback(err);
}
//为name属性添加索引
collection.ensureIndex("name", { unique: true });
//写入user文档
collection.insert(user, { safe: true }, function(err, user) {
mongodb.close();
callback(err, user);
})
})
})
};
User.get = function get(username, callback) {
mongodb.open(function(err, db) {
if (err) {
return callback(err);
}
//读取users集合
db.collection("users", function(err, collection) {
if (err) {
mongodb.close();
return callback(err);
}
//查找name属性为username的文档
collection.findOne({ name: username }, function(err, doc) {
mongodb.close();
if (doc) {
//封装文档为User对象
var user = new User(doc);
callback(err, user);
} else {
callback(err, null);
}
})
})
})
}
上面的代码实现了两个接口,User.prototype.save 和User.get ,前面的是对象实例方法,用于将用户对象的数据保存到数据库中,后者是对象的构造函数的方法,用于从数据库查找指定用户。
视图交互
为了实现不同的登录状态下呈现不同的视图内容的功能,我们需要创建动态的视图助手,通过它才能在视图中会话中的用户数据信息,同时为了显示错误和成功的信息,也要在动态视图助手中增加响应的函数。在app.js中添加:
app.use(function(req, res, next){
console.log("app.usr local");
res.locals.user = req.session.user;
res.locals.post = req.session.post;
var error = req.flash('error');
res.locals.error = error.length ? error : null;
var success = req.flash('success');
res.locals.success = success.length ? success : null;
next();
});
热门评论
数据库这块,我还没学习过,因此这部分在我学习了mongodb之后在进行更新。我正在学习mongodb,学习了mongodb再来完善它