第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,有想要一起做的,或者有什麼不懂的都可以找我哦。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章