【Node】nodejs+express+mongodb入门实例(二)

本文是Node.js、Express和MongoDB入门的第二部分,主要介绍了如何通过目录结构调整实现MVC模式,详细讲解了用户登录注册的流程,包括界面设计、服务器端处理、schema定义,以及用户登录时session的验证和用户注销的实现。
摘要由CSDN通过智能技术生成

【Node】nodejs+express+mongodb入门实例(一)
http://blog.csdn.net/whuzxq/article/details/73105978

一.目录调整

基于上一个部分的内容,app.js部分过于臃肿,不利于管理,因此对目录结构作出一些调整,让整个项目更符合MVC模式。
首先,新建config文件夹,并将路由相关的内容移入新建的route.js中。效果如下:
这里写图片描述
之前在app.js中的结构改成:

require('./config/routes')(app)

之后,继续对config.js的内容进行调整,改成mvc的格式:新建app文件夹,将models和schemas文件夹放入进去,并新建controller文件夹,在该文件夹中创建index.js,movie.js,user.js等,分别存放处理相应对象的方法。具体的目录结构如下图所示:
这里写图片描述

config.js变成了
这里写图片描述

以此完成了目录格式的优化。

二.用户登陆注册

注:hash算法:不可逆的,把任意长度的数据转化成固定的指纹
会话:用来跟踪用户,确定用户的身份。
session:当程序需要为客户端的请求创建session的时候,服务器首先检查客户端里面是否包含一个seesion的标示(sessionid),服务器根据此把它找出来,否则创建一个sessionid。保存sessionid可以放在cookie。一般情况下session存在内存里,若设置了session持久化的特性,那么清空内存后可以再次使用。
1.界面

lock content
  .container
    .row
      .col-md-5
        form(method="POST", action="/user/signup")//这里,定义路由。
          .modal-body
            .form-group
              label(for="signupName") 用户名
              input#signupName.form-control(name="user[name]", type="text")
            .form-group
              label(for="signupPassword") 密码
              input#signupPassword.form-control(name="user[password]", type="text")
          .modal-footer
            button.btn.btn-default(type="button", data-dismiss="modal") 关闭
            button.btn.btn-success(type="submit") 提交

2.服务器端:

exports.signup = function(req, res) {
  var _user = req.body.user

  User.findOne({name: _user.name},  function(err, user) {
    if (err) {
      console.log(err)
    }

    if (user) {
      return res.redirect('/signin')
    }//如果user存在,则重定向到登陆。
    else {
      user = new User(_user)//新建user对象
      user.save(function(err, user) {
        if (err) {
          console.log(err)
        }

        res.redirect('/')//跳转回首页
      })
    }
  })
}

3.schema:

var mongoose = require('mongoose')
var bcrypt = require('bcrypt')//加密密码
var SALT_WORK_FACTOR = 10

var UserSchema = new mongoose.Schema({
  name: {
    unique: true,
    type: String
  },
  password: String,
  // 0: nomal user
  // 1: verified user
  // 2: professonal user
  // >10: admin
  // >50: super admin
  role: {
    type: Number,
    default: 0
  },
  meta: {
    createAt: {
      type: Date,
      default: Date.now()
    },
    updateAt: {
      type: Date,
      default: Date.now()
    }
  }
})

UserSchema.pre('save', function(next) {
  var user = this

  if (this.isNew) {
    this.meta.createAt = this.meta.updateAt = Date.now()
  }
  else {
    this.meta.updateAt = Date.now()
  }

  bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
    if (err) return next(err)

  bcrypt.hash(user.password, salt, function(err, hash) {
      if (err) return next(err)
      user.password = hash
      next()
    })
  })
})
//对象调用
UserSchema.methods = {
  comparePassword: function(_password, cb) {
    bcrypt.compare(_password, this.password, function(err, isMatch) {
      if (err) return cb(err)

      cb(null, isMatch)
    })
  }
}
//模型可以直接调用
UserSchema.statics = {
  fetch: function(cb) {
    return this
      .find({})
      .sort('meta.updateAt')
      .exec(cb)
  },
  findById: function(id, cb) {
    return this
      .findOne({_id: id})
      .exec(cb)
  }
}

module.exports = UserSchema

三.用户登陆

1.界面

block content
  .container
    .row
      .col-md-5
        form(method="POST", action="/user/signin")
          .modal-body
            .form-group
              label(for="signinName") 用户名
              input#signinName.form-control(name="user[name]", type="text")
            .form-group
              label(for="signinPassword") 密码
              input#signinPassword.form-control(name="user[password]", type="text")
          .modal-footer
            button.btn.btn-default(type="button", data-dismiss="modal") 关闭
            button.btn.btn-success(type="submit") 提交

2.服务器端

// signin
exports.signin = function(req, res) {
  var _user = req.body.user
  var name = _user.name
  var password = _user.password

  User.findOne({name: name}, function(err, user) {
    if (err) {
      console.log(err)
    }
    //若用户不存在
    if (!user) {
      return res.redirect('/signup')
    }
    //比较密码是否相同
    user.comparePassword(password, function(err, isMatch) {
      if (err) {
        console.log(err)
      }

      if (isMatch) {
        req.session.user = user//设定session

        return res.redirect('/')//若相同,则设置session,并重定向到首页
      }
      else {
        return res.redirect('/signin')
      }
    })
  })
}

在最开始,要检验session是否存在

// pre handle user
  app.use(function(req, res, next) {
    var _user = req.session.user


    next()//啥时候写next啥时候不写?晕
  })

app.js

app.use(express.cookieParser())//session本身依赖这个包
app.use(express.session({
  secret: 'imooc',
}))//用session之前要引入

三.用户注销

// logout
exports.logout =  function(req, res) {
  delete req.session.user
  //delete app.locals.user

  res.redirect('/')
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值