您的位置:首页 > Web前端 > Node.js

nodejs实现登录注册系统

2017-02-11 15:10 330 查看

nodejs实现登录注册系统

对上一次的功能进一步的完善,将用户的数据储存在本地数据库,实现登录的功能,采用session机制记录登录信息,使得已登录的用户保持登录状态

目录结构

目录结构比较简单,算是一个小的demo



model是数据层,将采用mongoose创建数据库模型,并提供接口

public是静态资源,随http发送请求并加载

routes是控制层,包含路由控制和逻辑处理

views是视图层,主要有三个页面

signin是入口文件

数据处理

Mongoose是一个提供了MongoDB地相映射的Node.js库,创建一个数据库模型schema,并将其发布成为model,统一数据模型并能进行操作

var mongoose = require("mongoose");
mongoose.connect('mongodb://localhost/test');
var Schema = mongoose.Schema;
//骨架模版
var userSchema = new Schema({
username   : String,
password   : String,
id    : String,
phone : String,
email  : String
})
var User = mongoose.model('User', userSchema);
module.exports = User;


路由控制

主要是由routes.js控制,注意要加载静态资源和对session的设置,注册中间件

var express = require('express')
var routes = require('./server')
var app = express();
var bodyParser = require('body-parser');
var session = require('express-session')
// 创建 application/x-www-form-urlencoded 编码解析
var urlencodedParser = bodyParser.urlencoded({ extended: false })

module.exports = function(app) {
// 设置页面的跳转还有session的设置
app.use(session({ secret: 'keyboard cat', cookie: { maxAge: 60000 }}))
app.use('/',routes);
app.use('/regist',routes);
app.use('/logout',routes);
app.use('/info',routes);
app.use('/check', routes);
app.use(express.static(__dirname + '/public'));
}


逻辑处理

路由的控制还是在server.js中对逻辑的处理,并选择渲染的页面

通过引入express.Router(),对其中的具体方法和回调函数进行处理

视图层的显示采用动态模板进行渲染,因此render进行页面渲染的时候也提供了必要的数据

对于用户登录的和退出时通过请求req.session对登录状态进行标示

处于安全性考虑,数据库直接存放用户的密码,进行加密后判断

router.get('/regist',function (req, res) {
res.render('index.ejs', {
errorInfo:'请输入信息'
})
})
router.get('/',function(req, res) {
// 默认登录到index要判断扥估状态,已经登录的用户进入详情页面
if (!req.session.logged_in) {
Notlogin(req, res)
} else {
loggedIn(req, res)
}
})
//退出登录的用户进入登录页面
router.get('/logout', function(req, res) {
req.session.logged_in = 0;
res.render('signin.ejs', {
errorInfo:'请输入信息'
})
})
//登录处理
router.post('/check', urlencodedParser, function (req, res) {
console.log("check password");
var testuser = {
username:req.body.username,
password:req.body.password,

}
//这里采用md5对密码进行加密后在储存到数据库当中
var d = getMD5Password(testuser.password)
console.log("加密的结果:(验证)"+d);
testuser.password = d;
//采用model的方法,已经提供了各种接口,查找数据库中是否有次用户的信息,对用户登录进行验证
User.find(testuser, function (err, detail) {
if (detail.length) {
signinCheckSuccess(detail, req, res)
} else {
console.log("wrong!");
errorInfo = "用户名不存在或密码错误";
res.render('signin.ejs',{
errorInfo:errorInfo
})
}
})
})
//注册处理
router.post('/info', urlencodedParser, function(req, res) {
console.log("Data from submit form");
var user = new User({
username:req.body.username,
password:req.body.password,
id:req.body.id,
phone:req.body.phone,
email:req.body.email
})
var d = getMD5Password(user.
4000
password);
console.log("加密的结果:"+d);
user.password = d;
console.log(user);
var flag = {one:1,two:1,three:1,four:1};
errorInfo = "";
//这里对数据进行验证,不能够有重复的数据
checkDataRep(user, flag, req, res);
})


其他工具函数

主要针对是否有用户登录之后的一些逻辑的判断,以及对数据库查找的格式进行统一,处理回调函数

// 验证用户注册提交的表单,如果没有问题,则记录登录状态
function dealWithDataSubmited (user, flag, req, res) {
if (!(flag.one&&flag.two&&flag.three&&flag.four)) {
repreload(res);
} else {
req.session.username = user.username;
req.session.logged_in = 1;
user.save(function(err) {
if (err) {
console.log('保存失败');
return;
}
console.log('保存成功');
})
console.log(user.username + " has been added");
showInfo(user, res)
}
}
// user的find方法采用json格式,因此将传进去的名字转化为json格式之后对数据库进行访问,并处理逻辑,渲染页面
function findJson(name, res) {
var testUsername = {username:name};
User.find(testUsername,function (err, userDetail) {
if (userDetail.length == 0) {
console.log(userDetail);
res.render('index.ejs', {
errorInfo:'请输入信息'
});

} else {
console.log(userDetail);
console.log("Load user: " + name);
console.log(userDetail[0]);
showInfo(userDetail[0], res);
}
})
}
// 对用户访问index页面的逻辑进行处理,主要是看url后面有没有附带信息
function Notlogin(req, res) {
if (req.param("username") == undefined) {
console.log("initial page");
res.render('signin.ejs', {
errorInfo:'请输入信息'
})
} else {
var username = req.param("username").toString();
console.log("find user: " +  username);
findJson(username, res)
}
}
// 如果已经有用户登录了就显示当前登录的用户
function loggedIn(req, res) {
if (req.param("username") == undefined) {
findJson(req.session.username, res);
} else {
var username = req.param("username").toString();
console.log(username);
// 不能显示非当前登录用户的信息
if (username != req.session.username) {
var testUsername = {username:req.session.username};
User.find(testUsername,function (err, userDetail) {
infoPage(res, userDetail, "只能显示已登录用户")
})
} else {
var testUsername = {username:req.session.username};
User.find(testUsername,function (err, userDetail) {
infoPage(res, userDetail, "用户详情")
})
}
}
}
function getMD5Password(content) {
var md5 = crypto.createHash('md5');//定义加密方式:md5不可逆,此处的md5可以换成任意hash加密的方法名称;
md5.update(content);
var d = md5.digest('hex');  //加密后的值d
return d;
}
// 处理数据,注意格式
function signinCheckSuccess(detail, req, res) {
var userInDatabase = {
username:detail[0].username,
userId:detail[0].id,
phone:detail[0].phone,
email:detail[0].email
}
console.log("user in database :");
console.log(userInDatabase);
req.session.logged_in = 1;
req.session.username = req.body.username;
showInfo(userInDatabase, res);
}
function infoPage(res, userDetail, errorInfoDetail) {
res.render('info.ejs', {
username:userDetail[0].username,
userId:userDetail[0].id,
phone:userDetail[0].phone,
email:userDetail[0].email,
errorInfo:errorInfoDetail
})
}
function showInfo(user, res) {
res.render('info.ejs', {
username:user.username,
userId:user.id,
phone:user.phone,
email:user.email,
errorInfo:'用户详情'
});
}
function checkDataRep(user, flag, req, res) {
// 逐一验证储存的信息是否重复
var testUsername = {username:user.username};
var testId = {id:user.id};
var testPhone = {phone:user.phone};
var testEmail = {email:user.email};
User.find(testUsername, function (err, detail) {
if (detail.length) {
flag.one = 0;
errorInfo = errorInfo + "用户名重复\n";
}
})
User.find(testId, function (err, detail) {
if (detail.length) {
flag.two = 0;
errorInfo = errorInfo + "id重复\n";
}
})
User.find(testPhone, function (err, detail) {
if (detail.length) {
flag.three = 0;
errorInfo = errorInfo + "电话号码重复\n";
}
})
User.find(testEmail, function (err, detail) {
if (detail.length ) {
flag.four = 0;
errorInfo = errorInfo + "邮箱重复\n";
}
dealWithDataSubmited(user, flag, req, res)
})
}
function repreload(res) {
res.render('index.ejs',{
errorInfo:errorInfo
})
}


源码地址

github

总结

其实这一次的后端代码其中逻辑处理是比较复杂的,存在很大的优化空间,提高代码的可读性.而使用express框架和mongodb数据库模型的时候对一些api的时候来完成相应功能,是比较方便而且高效,其功能的强大远远不止于此。而对于项目的构建,可采用

express -e myapp

来生成目录,(-e表示ejs模板)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  nodejs