手记

《Node.js开发指南》microblog手动代码六

注册和登录

上一节准备好了数据库访问和会话存储的相关信息,这一节实现网站的用户注册和登录功能页面。

一,注册页面
先设计用户注册页面的表单,创建一个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();
    });
1人推荐
随时随地看视频
慕课网APP

热门评论

数据库这块,我还没学习过,因此这部分在我学习了mongodb之后在进行更新。我正在学习mongodb,学习了mongodb再来完善它

查看全部评论