通过Nodejs搭建网站简单实现注册登录流程


Posted in NodeJs onJune 14, 2019

1. 使用Backbone实现前端hash路由

初步设想将注册和登录作为两个不同的url实现,但登录和注册功能的差距只有form表单部分,用两个url实现显然开销过大,所以最终方案为使用hash作为前端路由,根据url的hash值切换相应的表单显示。

很多致力于SPA开发的前端框架都具备hash路由功能,考虑到嗨猫本身是一个类博客、偏重静态展示的网站,所以最后选择了轻量级的Backbone最为前端框架。

Backbone实现hash路由的代码很简单:

let $formBox = $('.box_form_container'),
$navitems = $('.box_nav_item'),
$nav_item_signup = $('.box_nav_item_signup'),
$nav_item_login = $('.box_nav_item_login');
let pwdRouter = Backbone.Router.extend({
routes: {
'login': 'login',
'signup': 'signup'
},
login: function() {
$formBox.removeClass('box_form_container_signup').addClass(
'box_form_container_login');
$navitems.removeClass('box_nav_item-current');
$nav_item_login.addClass('box_nav_item-current');
},
signup: function() {
$formBox.removeClass('box_form_container_login').addClass(
'box_form_container_signup');
$navitems.removeClass('box_nav_item-current');
$nav_item_signup.addClass('box_nav_item-current');
}
});
let router = new pwdRouter();
Backbone.history.start();

务必不要遗漏Backbone.history.start();,否则路由功能不会启动。

随后,将登录和注册的a标签的href分别修改为#login和#signup便实现了简单的hash路由。

2. 使用jquery-validation完善前端表单验证

前端表单验证是必不可少的一项功能,前端的js代码验证表单的完整性并拦截一部分非法的表单输入,一定程度上减少服务端的压力。

初步想自己造轮子,但考虑到开发周期和轮子的成熟性,最终选择jquery-validation插件作为前端表单验证工具。

jquery-validation插件和表单元素的name属性绑定,以登录表单为例,其dom结构如下:

根据input控件的name属性,jquery-validation的验证代码如下:

// 登录表单添加验证规则
$('.login_form').validate({
rules: {
signname: {
required: true,
signname: true
},
password: {
required: true,
norepeat: true
},
verifycode: {
required: true
}
},
errorPlacement: function(error, element) {
let container = element.parent().find('.form_error');
error.appendTo(container);
container.show();
},
submitHandler: function(form) {
var $form = $(form);
let _action = $form.attr('action');
$form.attr('action', '');
$.ajax({
type: 'post',
url: _action,
data: $form.serialize(),
dataType: 'json'
}).done(function(res) {
console.log('done');
if (res.code !== '100') {
alert(res.msg);
} else {
alert('注册成功');
}
}).fail(function(res) {
console.log('fail');
}).always(function() {
$form.attr('action', _action);
});
}
});

其中signname和norepeat是自定义的验证规则,signname如下:

// 添加用户名+邮箱的双重验证规则
$.validator.addMethod('signname', function(value, element) {
let reg_isemail = /[@]/,
reg_email =
/^[a-z]([a-z0-9]*[-_]?[a-z0-9]+)*@([a-z0-9]*[-_]?[a-z0-9]+)+[\.][a-z]{2,3}([\.][a-z]{2})?$/i;
return !reg_isemail.test(value) || (reg_isemail.test(value) &&
reg_email.test(value));
}, '请输入正确的用户名或邮箱');

用户可以使用用户名或邮箱登录,两者共享一个input控件,signname验证是用户名还是邮箱,如果是邮箱,便保证输入邮箱格式的正确性。

norepeat验证密码不能出现连续3次的字符

  • errorPlacement指明错误提示信息的位置,我们给它提供了一个容器。
  • submitHandler监听submit按钮,首先拦截默认的表单提交请求,替换为自定义的提交逻辑,本项目中使用ajax提交。

并且为了防止用户频繁点击submit按钮造成重复提交,我们首先将form的action属性清空,待请求完毕后重新赋值。

3. 使用node-canvas模块增加验证码功能

node-canvas是一个将canvas API迁移到nodejs使用的扩展模块,使用node-canvas模块可以在nodejs服务器生成图片(当然它的作用不仅限于此,但项目暂时只用到生成图片功能),下面详细讲述如何搭建登录&注册表单验证码功能。

3.1 部署node-canvas依赖环境

node-canvas需要操作系统安装底层图形库,各操作系统的依赖如下:

11111111111

目前开发环境为mac,简单记录一下环境部署操作以及遇到的一些坑。

首先按照上图安装底层库,由于brew安装的Cairo版本过低,将会导致canvas不正确的绘图(参考https://github.com/Automattic/node-canvas/issues/639)。这是Cairo的bug,所以必须保证Cairo版本在1.14.1以上。使用brew更新Cairo:

brew update
brew upgrade Cairo

安装成功后,在项目根目录下安装node-canvas:npm install canvas --save-dev 

至此,环境部署完毕,进入开发阶段。

3.2 服务端

打开api/controllers/Auth/AuthController,添加生成验证码图片的函数generateVerifyImg():

generateVerifyImg: function() {
var _verify = {
code: '',
img: ''
};
// 生成四位数字和字母的数字作为验证码
_verify.code = Math.random().toString(16).slice(2, 6);
var Image = Canvas.Image,
canvas = new Canvas(60, 30),
ctx = canvas.getContext('2d');
var _rotate = (Math.random()).toFixed(2);
ctx.fillStyle = '#ffcc99';
ctx.fillRect(0, 0, 60, 30);
ctx.rotate(_rotate);
ctx.font = 'italic 20px serif';
ctx.strokeStyle = '#424952';
// 将验证码绘制进canvas
ctx.strokeText(_verify.code, 10, 20);
// 生成验证码图片
_verify.img = canvas.toDataURL('image/png');
return _verify;
}

然后在登录&注册的API中生成验证码图片并渲染进模板文件:

/**
* @desc 登录、注册的统一入口,由前端Backbone的hash路由判断展示表单
* @param req
* @param res
*/
toAuth: function(req, res) {
var _verify = this.generateVerifyImg();
req.session.verifycode = _verify.code;
var view = swig.renderFile('./views/passport/main.swig', {
verify_img: _verify.img
});
return res.send(view);
}

其中非常关键的一步是将验证码通过session保存,以便进行验证。

随后,在接受表单post的API中加入验证码过滤逻辑:

if (!req.param('verifycode') || req.param('verifycode') !== req.session
.verifycode) {
return res.json({
err: rescode.invalidVerifycode,
msg: "验证码不正确"
});
}

项目至此已经具备了基本的验证码功能。验证码的一个重要需求是用户手动刷新验证码,下面简单讲述实现过程。

3.3 实现验证刷新功能

1.首先在前端js代码中添加验证码图片刷新事件监听:

$('.hc_container').on('click', '.form_img_verifycode', function() {
console.log('换一换');
var $img = $(this);
$.ajax({
url: '/getverifycode',
type: 'get',
dataType: 'json'
}).done(function(res) {
console.log('getverifycode success');
$img.attr('src', res.img);
}).fail(function(res) {
console.log('getverifycode failed');
});
});

2.然后配置sails的config/route.js:

// 刷新验证码
'get /getverifycode': 'Auth/AuthController.getVerifyImg'

3.在Auth/AuthController中添加getVerifyImg()API接受前端的验证码刷新请求:

getVerifyImg: function(req, res) {
var _verify = this.generateVerifyImg();
req.session.verifycode = _verify.code;
return res.json({
'img': _verify.img
});
}

这个API功能非常简单,获取新的验证码图片并返回给前端,但是必须谨记将验证码通过session记录。

前端通过ajax获取到新的验证码图片url替换旧图即可。

4. 实现登录&注册成功后的页面跳转
由前端js控制跳转,目前统一跳转到首页:

window.location.href='/';

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

NodeJs 相关文章推荐
将nodejs打包工具整合到鼠标右键的方法
May 11 NodeJs
nodejs npm包管理的配置方法及常用命令介绍
Jun 05 NodeJs
基于NodeJS+MongoDB+AngularJS+Bootstrap开发书店案例分析
Jan 12 NodeJs
nodejs个人博客开发第四步 数据模型
Apr 12 NodeJs
NodeJS收发GET和POST请求的示例代码
Aug 25 NodeJs
NodeJS实现不可逆加密与密码密文保存的方法
Mar 16 NodeJs
nodejs 简单实现动态html的方法
May 12 NodeJs
NodeJs项目中关闭ESLint的方法
Aug 09 NodeJs
nodejs 如何手动实现服务器
Aug 20 NodeJs
nodejs实现范围请求的实现代码
Oct 12 NodeJs
使用nodeJS中的fs模块对文件及目录进行读写,删除,追加,等操作详解
Feb 06 NodeJs
NodeJs生成sitemap站点地图的方法示例
Jun 11 #NodeJs
nodejs提示:cross-device link not permitted, rename错误的解决方法
Jun 10 #NodeJs
Nodejs异步流程框架async的方法
Jun 07 #NodeJs
nodejs log4js 使用详解
May 31 #NodeJs
如何让Nodejs支持H5 History模式(connect-history-api-fallback源码分析)
May 30 #NodeJs
nodejs中实现修改用户路由功能
May 24 #NodeJs
nodejs实现用户登录路由功能
May 22 #NodeJs
You might like
yii框架表单模型使用及以数组形式提交表单数据示例
2014/04/30 PHP
PHP多进程编程实例
2014/10/15 PHP
PHP模拟登陆163邮箱发邮件及获取通讯录列表的方法
2015/03/07 PHP
在IE和VB中支持png图片透明效果的实现方法(vb源码打包)
2011/04/01 Javascript
jquery获取一组checkbox的值(实例代码)
2013/11/04 Javascript
各浏览器对document.getElementById等方法的实现差异解析
2013/12/05 Javascript
异步JavaScript编程中的Promise使用方法
2015/07/28 Javascript
javascript html5摇一摇功能的实现
2016/04/19 Javascript
AngularJS上拉加载问题解决方法
2016/05/23 Javascript
Node.js五大应用性能技巧小结(必须收藏)
2017/08/09 Javascript
JS加密插件CryptoJS实现的Base64加密示例
2020/08/16 Javascript
vue观察模式浅析
2018/09/25 Javascript
JavaScript中的相等操作符使用详解
2019/12/21 Javascript
JavaScript中ES6规范中let和const的用法和区别
2020/08/06 Javascript
js实现批量删除功能
2020/08/27 Javascript
python中实现迭代器(iterator)的方法示例
2017/01/19 Python
Python新手们容易犯的几个错误总结
2017/04/01 Python
python虚拟环境virtualenv的使用教程
2017/10/20 Python
python中pylint使用方法(pylint代码检查)
2018/04/06 Python
python3解析库lxml的安装与基本使用
2018/06/27 Python
Python中修改字符串的四种方法
2018/11/02 Python
在Pandas中DataFrame数据合并,连接(concat,merge,join)的实例
2019/01/29 Python
Python之lambda匿名函数及map和filter的用法
2019/03/05 Python
使用python实现mqtt的发布和订阅
2019/05/05 Python
Python正则表达式实现简易计算器功能示例
2019/05/07 Python
python+logging+yaml实现日志分割
2019/07/22 Python
python 装饰器功能与用法案例详解
2020/03/06 Python
乡镇消防工作实施方案
2014/03/27 职场文书
2014最新预备党员思想汇报范文:中国梦,我的梦
2014/10/25 职场文书
2015大学自主招生自荐信范文
2015/03/04 职场文书
2016党员学习心得体会范文
2016/01/23 职场文书
写好Python代码的几条重要技巧
2021/05/21 Python
Python 实现绘制子图及子图刻度的变换等问题
2021/05/31 Python
室外天线与收音机天线杆接合方法
2022/04/05 无线电
Redis keys命令的具体使用
2022/06/05 Redis
shell进度条追踪指令执行时间的场景分析
2022/06/16 Servers