欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

前后端分离编写简单注册登录案例,并实现session存储持久化

程序员文章站 2022-07-10 13:07:20
...

为加深对nodeJS服务端与客户端交互的理解,特写下这个案例,供以后查阅。

1. 编写mongoose连接模块(connect.js)

const mongoose = require('mongoose');

function mongoConnect(openFn, errorFn) {
    //连接数据库
    mongoose.connect('mongodb://localhost:27017/demo', {
        useNewUrlParser: true,
        useUnifiedTopology: true,
        useFindAndModify: false,
        useCreateIndex: true
      });

    //判断数据库连接状态,如果连接成功,调用回调函数openFn,如果出错,调用回调函数errorFn
    mongoose.connection.once('open', function(){
        openFn();
    })

    mongoose.connection.on('error', function(){
        closeFn();
    })
}

module.exports = mongoConnect;

2. 编写数据库模型模块(userModel.js)

const mongoose = require('mongoose');

//schema是mongoose里会用到的一种数据模式,可以理解为表结构的定义;每个schema会映射到mongodb中的一个collection,它不具备操作数据库的能力.
const {Schema} = mongoose;

const userSchema = new Schema({
    name: {
        type: String,
        required: true,
        unique: true
    },
    pwd: {
        type: String,
        required: true
    },
    phone: {
        type: Number,
        required: true,
        unique: true
    },
    creat_time: {
        type: Date,
        default: Date.now()
    }
})

//导出User模型,可供外部文件操作数据库
module.exports = mongoose.model('User', userSchema);

3. 编写数据库增删改查API模块(crudAPI)

因为案例只涉及注册登录,因此只编写需要的增加数据和查询数据API

const mongoose = require('mongoose');

//引入数据库user集合模型
const userModel = require('./model/userModel');

module.exports = {
    //添加数据库
    create: function (o, callback) {
        userModel.create(o, function (err, ret) {
            if (err) return callback(err);
            callback(null);
        })
    },

    //查询数据库
    findOne: function(o, callback) {
        userModel.findOne(o, function(err, ret){
            if(ret) return callback(ret);
            callback(null);
        })
    },
    findById: function(id, callback) {
        userModel.findById(id, function(err, ret) {
            if(ret) return callback(ret);
            callback(null);
        })
    }
}



4. 编写项目入口文件(app.js)

const express = require('express');

//引入express-session模块,用于简化操作session
const session = require('express-session');

//引入connect-mongo模块,用于session持久化存储
const MongoStore = require('connect-mongo')(session);

//引入数据库连接模块
const mongoConnect = require('./dataBase/connect');

//引入中间件body-parser用于解析post请求参数
const bodyParser = require('body-parser');

const app = express();

//配置express-session中间件
app.use(session({
    name: "user_id",
    saveUninitialized: false,
    resave: true,
    secret: 'ting',
    store: new MongoStore({
        url: 'mongodb://localhost:27017/session_container',
        touchAfter: 24 * 3600
    }),
    cookie: {
    	httpOnly: true,
        maxAge: 1000 * 60
    }
}))
//配置中间件body-parser解析urlencode编码的参数
app.use(bodyParser.urlencoded({extended: true}));
//配置中间件body-parser解析json格式的参数
app.use(bodyParser.json());

//配置静态目录
app.use('/static/', express.static('./public'))

//配置模板引擎art-template,设置为views文件夹(默认)下的.html文件进行渲染
app.engine('html', require('express-art-template'));

mongoConnect(function(){
    //导入路由模块
    app.use(require('./route/router'));
    
    //开启服务监听端口
    app.listen(3000, function(err){
        if(err) return console.log(err);
        console.log('server running...');
    })
}, function(){
    console.log('数据库连接失败');
})



5. 编写路由模块(router.js)

这里只对注册的两次密码是否一样和注册账号是否已经注册进行了验证,完整的验证逻辑不在本文展示

const express = require('express');
const route = express.Router();

const crud = require('../dataBase/crudAPI');
const md5 = require('md5');

//访问登陆页面
route.get('/login', function (req, res) {
    res.render('login.html');
})

//登陆提交
route.post('/login', function (req, res) {
    let {name, pwd} = req.body;

    //验证数据
    crud.findOne({name, pwd: md5(pwd)}, function (data) {
        if (!data) return res.render('login.html', {
            loginErr: "用户名或密码错误"
        });

        //进入个人中心
        req.session._id = data._id.toString();

        res.redirect('/user_center');
    })
})

//访问注册页面
route.get('/register', function (req, res) {
    res.render('register.html');
})

//注册提交
route.post('/register', function (req, res) {

    let { name, pwd, pwd_re, phone } = req.body;

    //判断账号是否已经注册
    crud.findOne({ name }, function (data) {
        if (data) return res.render('register.html', {
            registerErr: "该账号已注册"
        });

        //判断两次输入密码是否一致
        if (pwd !== pwd_re) {
            return res.render('register.html', {
                pwd_reErr: "两次密码不一致"
            });
        }

        //添加数据
        crud.create({ name, pwd: md5(pwd), phone }, function (err) {
            if (err) return res.status(500).send('注册失败,请稍后重试');
            res.redirect('/login');//注册成功,重定向到登录页面
        })

    })
})

//访问个人中心页面,用户在cookie有效期内访问该页面都能直接进入,否则需要重新登录
route.get('/user_center', function(req, res){
    //获取请求cookie对应的session中存储的id
    let {_id} = req.session;
    //如果没有_id,说明用户的登录cookie已过期或者用户没有登录
    if(!_id) {
        return res.redirect('/login');
    }
    //根据id去数据库中查找出相应的用户名
    crud.findById(_id, function(data) {
        if(!data) return res.redirect('/login');
        res.render('user_center.html', {name: data.name})
    })

    
})  

module.exports = route;

6. 编写渲染页面

前后端分离编写简单注册登录案例,并实现session存储持久化

7. 操作记录

前后端分离编写简单注册登录案例,并实现session存储持久化

前后端分离编写简单注册登录案例,并实现session存储持久化
前后端分离编写简单注册登录案例,并实现session存储持久化
前后端分离编写简单注册登录案例,并实现session存储持久化

关闭user_center页面后再次访问,如果在cookie有效期内,能直接进入用户个人中心,如果超过有效期或清除了缓存,将跳转到登录页面