第4章 实现用户登录和注册功能

请关注我的小站:http://oideas.herokuapp.com/

不好意思,说明一下,本来的话今天应该能够把前两天段更的blog写完,但是,恩,周五的下班之前,老大直接给我来一句“你还是装linux系统吧”,我,好吧,昨晚搞了一晚上,结果无线总是连不上,今天出去买了跟线,插上,装好各种环境,不知不觉已经到现在了,我去,想着blog还没跟,赶紧的。。。不多说了,总之就是告诉大家,我在用linux,而且还是个菜鸟,无言以对了。。。。
1.各功能实现说明
最新,毋庸置疑,应该就是我们的网站首页,那么,上一章已经实现的差不多了,下面打开views下的headere.ejs文件,将:

<li><a href="#" title="8小时内最新">最新</a></li>

修改为:

<li><a href="/" title="8小时内最新">最新</a></li>

ok这个功能暂时这样。

精华,这个功能应该是显示评论最多,赞最多,并且最新的,所以这个跟【最新】这个共能是差不多的,只不过是排序不一样
投稿,已经实现。
关于,属于扯淡的东西,自己想。
博客,可以链接到你自己的博客,或者实现它,项目最后,如果我还有精力,会带着大家实现。
搜索,这个其实就是最新或精华的另一种显示而已。
然后就是今天的登录和注册了。

2.布局登录界面和注册界面
为什么我对界面看如此重要,就好比人的脸一样,有些人让你看一样之后就想吐,而有些人让你看了还想看,这就是我想说的。
本来是想做成弹出窗口的形式,但是浏览了不下于30多个国外的网站,都没找到我想要的,国内几个比较知名的我是知道的,都没有看,无奈之下拿个以前做的修修,真不是想敷衍大家,而是自己想要的样子很模糊,自己做出来又要浪费很长时间,所以直接开始把。
登录界面:
上一章加了投稿功能,但是是是用户未登录模式的,我们肯定也是需要用户登录的,好,打开style.css文件,追加css:

.form-login {
	background: #fff;
	right: 0px;
	margin: 0px auto;	
	margin-top:40px;
	width: 400px;
}
.header {
	background: #e84c3d;
	text-align:center;
	font-size:18px;
	padding:20px 25px;
	color:#4d4d4d;
}
.inputs {
	margin-top:10px;
	color:#4d4d4d;
}
.inputs input[type="text"], .inputs [type="password"], .inputs [type="email"] {
	width:340px;
	height:45px;
	background:url(../images/bgnoise_lg.png) repeat left top;
	color:#4d4d4d;
	font-size:16px;
	margin-top:15px;
	-webkit-border-radius: 4px;
	-moz-border-radius: 4px;
	border-radius: 4px;
	border:0;
	margin-left:20px;
	padding:0px 10px;
}
.inputs input[type="text"]:hover, .inputs input[type="text"]:focus,.inputs [type="password"]:hover, .inputs [type="password"]:focus,.inputs [type="email"] :hover,.inputs [type="email"] :focus{
	outline:none;	
}
.link-2 {
	float:right;
	margin-top:15px;
	margin-right:20px;
}
.link-2 a, .link-2 a:hover {
	color:#4d4d4d;
}
.link-2 a:hover {
	text-decoration:none;
}

.button-login input[type="submit"] {
	width:360px;
	height:55px;
	margin-left:20px;
	margin-top:25px;
	margin-bottom:40px;
	font-size:18px;
	font-weight:bold;
	text-transform:uppercase;
	outline: none;
	position: relative;
	cursor: pointer;
	border-radius: 5px;
	color: #fff;
	border:0;
	background: #e84c3d;
}
.button-login input[type="submit"]:hover { opacity:0.9; }
.button-login input[type="submit"]:active {
	top: 3px;
	background: #e84c3d;
	box-shadow: inset 0 1px 2px #ba3c30;
}

在views 下新建ologin.ejs和oregist.ejs,  其中ologin.ejs如下:

<%- include header%>
	<form action="/dologin" class="form-login" method="post" id="login_form">
		<div class="header">
			OMinds-登录
		</div>
		<div class="inputs">
			<span style="padding:10px 15px;color:red;" id="error"><%=error%></span>
			<input id="email" name="email" type="text" required="" placeholder="邮箱">
			<input id="passw" name="passw" type="password" required="" placeholder="密码">
			<div class="link-2">
				<a 	href="/forget">忘记密码?</a>
			</div>
			<div class="clear">
			</div>
			<div class="button-login">
				<input type="button" value="登 录" id="login_btn">
			</div>
		</div>
	</form>
<%- include footer%>


oregist.ejs内容:

<%- include header%>
	<form action="/doregist" class="form-login" method="post" id="regist_form">
		<div class="header">
			OMinds-注册
		</div>
		<div class="inputs">
			<span style="padding:10px 15px;color:red;" id="error"><%=error%></span>
			<input id="reg_nickname" name="reg_nickname" type="text" required="" placeholder="昵称">
			<input id="reg_email" name="reg_email" type="text" required="" placeholder="邮箱">
			<input id="reg_passw" name="reg_passw" type="password" required="" placeholder="密码">
			<input id="reg_repassw" name="reg_repassw" type="password" required="" placeholder="密码确认">
			<div class="link-2">
				<a 	href="/login">已有帐号?</a>
			</div>
			<div class="clear">
			</div>
			<div class="button-login">
				<input type="button" value="注 册" id="regist_btn">
			</div>
		</div>
	</form>
<%- include footer%>


内容没有多大区别,就是regist中比login多了几个框而已。

ok,修改header.ejs文件,将:

<li><a href="#" >登录</a></li>
<li><a href="#">注册</a></li>

修改为:

<li><a href="/login" >LOG</a></li>
<li><a href="/regist">REG</a></li>

我装b了,你可以不用把登录和注册换成英文,我是自己玩的happy了~~~

接下来在routes/index.js中,添加:

 app.get('/login', function (req, res) {
	  res.render('ologin', {
		title : 'OMinds - 登录' });
  });
  app.get('/regist', function (req, res) {
	  res.render('oregist', {
		title : 'OMinds - 注册' });
  });

好了,打开浏览其看一下效果把,登录效果:


注册效果:




好,我们先来实现注册的代码,首先注册的表单,一般要做个验证,或者你也可以把它交给后台验证,当然了,一般这种简单的验证还是放在前端的,好了,我们需要使用jquery,到官网下载 http://jquery.com/download/ 下载相关的版本,我的是1.7(下载的时候,有时候发现浏览器把js的内容打开了,不要紧,比可以复制下来保存,或者点击链接的时候选择连接另存为),
ok,把它放到,js文件夹下,在header.ejs中加入<script language="javascript" type="text/javascript" src="/js/jquery-1.7.1.min.js"></script>
同时在js文件夹下新建common.js 内容如下:


$(document).ready(function(){
	var flag = false;
	$("#searckBtn").click(function(){
		if(!flag){
			$("#headbar").append("<li id=searchinput><from action=# ><input type=tex name=searchkey class=searck_input></form></li>");
		}else{
			$("#searchinput").remove();
		}
		flag = !flag;
	});
	$("#login_btn").click(function(){
		var email = $("#email").val();
		var passw = $("#passw").val();
		if(email==null||email.trim()==''||passw==null||passw.trim()==''){
			$("#error").text('邮箱或密码不能为空!');
			return;
		}else if(passw!=null&&(passw.length<6||passw.length>40)){
			$("#error").text('您输入的密码不符合要求,密码长度为6-40!');
			return;
		}
		$("#login_form").submit();
	});
	$("#regist_btn").click(function(){
		var nickname = $("#reg_nickname").val();
		var email = $("#reg_email").val();
		var passw = $("#reg_passw").val();
		var repassw = $("#reg_repassw").val();
		if(nickname==null||nickname.trim()==''){
			$("#error").text('昵称不能为空!');
			return;
		}else if(email==null||email.trim()==''){
			$("#error").text('邮箱不能为空!');
			return;
		}else if(passw==null||passw.trim()==''){
			$("#error").text('密码不能为空!');
			return;
		}else if(repassw==null||repassw.trim()==''){
			$("#error").text('请确认密码!');
			return;
		}else if(passw!=null&&(passw.length<6||passw.length>40)){
			$("#error").text('您输入的密码不符合要求,密码长度为6-40!');
			return;
		}
		$("#regist_form").submit();
	});
	
});

在header.ejs中加入<script language="javascript" type="text/javascript" src="/js/common.js"></script>

common.js中主要是监控登录和注册按钮的方法,细心的同学可能已经注意到还有一个searchbar的click方法,这个后面会说到。

前端的验证js中,输出错误怎么办呢?我也没法看到啊,对,那么需要我们再在ologin.ejs和oregist.ejs中添加一个标签,他们看起来应该是这样子的:

<span style="padding:10px 15px;color:red;" id="error"><%=error%></span>

放在哪里呢?当然是:

<div class="inputs">

代码之后了,以ologin.ejs为例,看最终代码:

<%- include header%>
	<form action="/dologin" class="form-login" method="post" id="login_form">
		<div class="header">
			OMinds-登录
		</div>
		<div class="inputs">
			<span style="padding:10px 15px;color:red;" id="error"><%=error%></span>
			<input id="email" name="email" type="text" required="" placeholder="邮箱">
			<input id="passw" name="passw" type="password" required="" placeholder="密码">
			<div class="link-2">
				<a 	href="/forgot-password">忘记密码?</a>
			</div>
			<div class="clear">
			</div>
			<div class="button-login">
				<input type="button" value="登 录" id="login_btn">
			</div>
		</div>
	</form>
<%- include footer%>

好,前端已经ok了,现在是后台,那么,我们要先建立user的表。在models文件夹下,新建user.js,内容:


var mongodb = require('./db');
var ObjectID = require('mongodb').ObjectID;


function User(user) {
	this.email = user.email;
	this.password = user.password;
	this.nickname = user.nickname;
	this.photo = user.photo;
	this.cdate = user.cdate;
	this._id = user._id;
};
module.exports = User;
// C(增)
User.prototype.save = function(callback) {
	var date = new Date();
	var time = date.getFullYear()+ "-"+ (date.getMonth() + 1)+ "-"+ date.getDate()+ " "+ date.getHours()+ ":"+ (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes())+ ":"+ (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds());
	var user = {
		email : this.email,
		password : this.password,
		nickname : this.nickname,
		photo : this.photo,
		cdate : time
	};
	mongodb.open(function(err, db) {
		if (err) {
			return callback(err);
		}
		db.collection('users', function(err, collection) {
			if (err) {
				db.close();
				return callback(err);
			}
			collection.insert(user, {
				safe : true
			}, function(err, user) {
				db.close();
				if (err) {
					return callback(err);
				}
				callback(null, user[0]);
			});
		});
	});
};


// R(查)
User.get = function(email, callback) {
	mongodb.open(function(err, db) {
		if (err) {
			return callback(err);
		}
		db.collection('users', function(err, collection) {
			if (err) {
				db.close();
				return callback(err);
			}
			collection.findOne({
				email : email
			}, function(err, user) {
				db.close();
				if (err) {
					return callback(err);
				}
				callback(null, user);
			});
		});
	});
};
// R(查,通过ID)
User.getById = function(id, callback) {
	mongodb.open(function(err, db) {
		if (err) {
			return callback(err);
		}
		db.collection('users', function(err, collection) {
			if (err) {
				db.close();
				return callback(err);
			}
			collection.findOne({
				_id : new ObjectID(id)
			}, function(err, user) {


				if (err) {
					return callback(err);
				}
				callback(null, user);
			});
		});
	});
};
// U (改)
User.update = function(user, callback) {
	mongodb.open(function(err, db) {
		if (err) {
			return callback(err);
		}
		db.collection('users', function(err, collection) {
			if (err) {
				mongodb.close();
				return callback(err);
			}
			collection.update({
				"email" : user.email}, {
				$set : {
					nickname : user.nickname,
					password : user.password,
					photo : user.photo
				}
			}, function(err) {
				mongodb.close();
				if (err) {
					return callback(err);
				}
				callback(null);
			});
		});
	});
};

没错,只有三类方法,为什么没有删除呢?为了增加用户,我们为什么还要删除方法?

好,下面开始做逻辑处理了,代开routes下的index.js 添加注册的方法:

app.post('/doregist',function (req, res){
	  	var email = req.body.reg_email;
		var nickname = req.body.reg_nickname;
	  	var md5 = crypto.createHash('md5'), password = md5.update(req.body.reg_passw).digest('hex');
		var mde = crypto.createHash('md5'), email_MD5 = mde.update(email.toLowerCase()).digest('hex');
		var newUser = new User({
			email : email,
			nickname : nickname,
			password : password,
			photo : "http://www.gravatar.com/avatar/" + email_MD5 + "?s=48"
		});
		User.get(newUser.email, function(err, user) {
			if (user) {
			req.flash('error', '该邮箱已注册,请登录或找回密码。');
			req.flash('email', email);
			req.flash('nickname', nickname);
			req.flash('password', password);
			req.flash('repassword', repassword);
			return res.redirect('/regist');
		}
		// 如果不存在则新增用户
		newUser.save(function(err, user) {
			if (err) {
				req.flash('error', err);
				req.flash('email', email);
				req.flash('nickname', nickname);
				req.flash('password', password);
				req.flash('repassword', repassword);
				return res.redirect('/regist');
			}
			req.session.user = user;
			res.redirect('/');
			});
		});
  });

其中密码做了md5加密,这没什么好说的(不可逆,别想着解密),头像功能,如果我说我想自己做一个有人觉得我能成功吗?恩,暂时用的是gravatar这个东西,s=48表示取得48*48大小的图片。注册成功了吗?恩,理论上是成功了,但是我们看不到结果,虽然已经将user写进session中了,但是我们却没有用,好,打开header.ejs文件将:
<ul style="margin-left:50px;float:right;">
			<li><a href="/login" >LOG</a></li>
			<li><a href="/regist">REG</a></li>
		</ul>
改为:

<ul style="margin-left:50px;float:right;">
			<%if(user) {%>
			<a href="#" class="user_icon" style="clear:both;padding: 0;"><img src="<%=user.photo%>" title="<%=user.nickname%>"></a>
			<%}else{%>
			<li><a href="/login" >LOG</a></li>
			<li><a href="/regist">REG</a></li>
			<%}%>
		</ul>

看起来是没问题了,但是用浏览器刷一下会发现找不到user,那是因为,我们在app.get('/')这个方法中没有传入啊,好把,在routes/index.js文件中的所有res.render中都加入代码:
user : req.session.user

最后index.js应该是这样的:

var crypto = require('crypto');
var Mind = require('../models/mind.js');
var User = require('../models/user.js');

//trim方法
function trimStr(str){
	if(str){
		return str.replace(/(^\s*)|(\s*$)/g,"");
	}
}

module.exports = function(app) {
  app.get('/', function (req, res) {
	  Mind.getAll(function(err, minds) {
		  if(err){
			  minds = [];
		  }
		  res.render('index', {
				title : 'OMinds - 最新',
				user : req.session.user,
				minds : minds });
	  });
  });
  app.get('/login', function (req, res) {
	  var use = req.session.user;
	  if(use){
		  return res.redirect('/');
	  }
	  res.render('ologin', {
		title : 'OMinds - 登录' ,
		user : req.session.user,
		error : req.flash('error').toString()});
  });
  app.get('/regist', function (req, res) {
	  res.render('oregist', {
		title : 'OMinds - 注册',
		user : req.session.user,
		error : req.flash('error').toString()});
  });
  app.get('/logout', function (req, res) {
	  delete req.session.user;
	 return res.redirect('/');
  });
  app.get('/upminds', function (req, res) {
	    res.render('upminds', { title: 'OMinds - 投稿' ,
	    	user : req.session.user,
	    	error : req.flash('error').toString(),
	    	ocontent:req.flash('ocontent').toString()
	    });
  });
  app.post('/doregist',function (req, res){
	  	var email = req.body.reg_email;
		var nickname = req.body.reg_nickname;
	  	var md5 = crypto.createHash('md5'), password = md5.update(req.body.reg_passw).digest('hex');
		var mde = crypto.createHash('md5'), email_MD5 = mde.update(email.toLowerCase()).digest('hex');
		var newUser = new User({
			email : email,
			nickname : nickname,
			password : password,
			photo : "http://www.gravatar.com/avatar/" + email_MD5 + "?s=48"
		});
		User.get(newUser.email, function(err, user) {
			if (user) {
			req.flash('error', '该邮箱已注册,请登录或找回密码。');
			req.flash('email', email);
			req.flash('nickname', nickname);
			req.flash('password', password);
			req.flash('repassword', repassword);
			return res.redirect('/regist');
		}
		// 如果不存在则新增用户
		newUser.save(function(err, user) {
			if (err) {
				req.flash('error', err);
				req.flash('email', email);
				req.flash('nickname', nickname);
				req.flash('password', password);
				req.flash('repassword', repassword);
				return res.redirect('/regist');
			}
			req.session.user = user;
			res.redirect('/');
			});
		});
  });
  app.post('/dologin', function(req, res) {
		var email = req.body.email;
		var md5 = crypto.createHash('md5');
		var password = md5.update(req.body.passw).digest('hex');
		User.get(email, function(err, user) {
			req.flash('email', email);
			console.log(user);
			if (!user) {
				req.flash('error', '邮箱或密码错误!');
				return res.redirect('/login');// 用户不存在则跳转到登录页
			}
			// 检查密码是否一致
			if (user.password != password) {
				req.flash('error', '邮箱或密码错误!');
				return res.redirect('/login');// 密码错误则跳转到登录页
			}
			// 用户名密码都匹配后,将用户信息存入 session
			req.session.user = user;
			res.redirect('/');// 登陆成功后跳转到主页
		});
	});
  app.post('/putup',function (req, res) {
	  	var user = req.session.user;
	  	var cont = trimStr(req.body.mind_text);
		if(cont==null||cont.length<40||cont.length>700){
			req.flash('error', "您的投稿不符合条件,请修改后提交。");
			req.flash('ocontent', cont);
			return res.redirect('/upminds');
		}
		var mind;
		var flag = true;
		//no login
		if (!user) {
			mind = new Mind({
				content : cont,
				user : null,
				flag : flag
			});
			mind.save(function(err, mind) {
				if (err) {
					req.flash('error', err);
					return res.redirect('/upminds');
				}
				res.redirect('/');
			});
		} 
		// login
		else {
			//暂时不做处理
		}
  	});
};

其中app.post('/dologin')为我们的登录方法,app.get('/logout')是退出方法。

以上我们已经实现了登录和注册,让我们看看效果:


看到右上角的头像了吗?对,我们没有退出按钮,为什么需要呢?其实在我写完app.get('/logout')方法的时候,突然想到不应个给退出,当然你可一自己手动退出,通过 /lougout去访问。
最后,前面提到的searchbar的click方法,既然js是显示的效果,那么,其他也没多少东西,打开header.ejs。将搜索的链接代码变为:

<li><a href="javascript:void(0);" id="searckBtn">搜索</a></li>

在style.css中加入:

.searck_input{
	padding: 7px 9px;
	border-radius: 0 100px 100px 0;
}
input.searck_input:focus{
	outline:none;
}

ok,效果:


看到红色画线框中的地方了吗?对 那就是我们做的效果。


以上,本章的登录和注册。。

ideas-ominds交流群: 158325682,有想要一起做的,或者有什么不懂的都可以找我哦。
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值